@gangfun/cli 0.13.0 → 0.14.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
@@ -87,8 +87,8 @@ gang bond burn --token <addr> | gang bond tx --hash <0x..> # push one buy-
87
87
  # A creator's gang sell (curve or pool) / gang withdraw below X is refused unless --break-bond (past T: --settle-first)
88
88
  # Launch in one command: one tx per run — execute it, run the very same command again, until launch.stage = done
89
89
  gang create … --dev-buy <quote> [--bond <quote> [--bond-hold <tokens|N%|all>] --bond-days <7-90>] # V3: create → dev buy → bond
90
- gang create … --buy-tax 3 --sell-tax 3 --buyback 50 [--dev-buy …] # V3: the recipient's part of the tax 50% bought back + burned, the rest to you
91
- gang buyback status|set|apply --token 0x… [--pct 0-100] # the buy-back splitter: ratio (raise now, cut after 3 days), what waits
90
+ gang create … --buy-tax 3 --sell-tax 3 --buyback 50 [--buyback-to 0x…] [--dev-buy …] # V3: the recipient's part of the tax 50% bought back + burned, the rest to you (or --buyback-to)
91
+ gang buyback status|set|set-payee|apply --token 0x… [--pct 0-100] [--to 0x…] # the buy-back splitter: ratio (raise now, cut after 3 days), payee (at once), what waits
92
92
  gang create --fair … [--shares <n>] --bond <quote> [--bond-hold …] --bond-days <7-90> # 打新: create (dev shares) → bond
93
93
  gang execute --request-id <id>
94
94
  gang tx --hash <0x..> [--testnet] # V2 / Soft and GangLaunchpad events (GangLaunchpad: units "raw", amounts in wei)
@@ -227,4 +227,4 @@ gang agents --window 30d --sort follow
227
227
 
228
228
  ## Version
229
229
 
230
- `0.13.0` · repo [gangfun/cli](https://github.com/gangfun/cli) · published to [npm](https://www.npmjs.com/package/@gangfun/cli) on push to `main`
230
+ `0.14.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
@@ -77,8 +77,8 @@ gang bond burn --token <addr> | gang bond tx --hash <0x..> # 推进一块
77
77
  # 创建者用 gang sell(内盘或外盘)/ gang withdraw 卖到低于 X 会被拒,除非加 --break-bond(过了 T:--settle-first 先取回)
78
78
  # 一条命令发射:每次运行产出一笔交易,执行后再运行同一条命令,直到 launch.stage = done
79
79
  gang create … --dev-buy <报价币数量> [--bond <数量> [--bond-hold <枚数|N%|all>] --bond-days <7-90>] # V3:发币 → dev 内盘买入 → 押金
80
- gang create … --buy-tax 3 --sell-tax 3 --buyback 50 [--dev-buy …] # V3:接收地址那份税 50% 回购销毁,其余给你
81
- gang buyback status|set|apply --token 0x… [--pct 0-100] # 回购合约:比例(提高立即生效,下调 3 天后)、待回购金额
80
+ gang create … --buy-tax 3 --sell-tax 3 --buyback 50 [--buyback-to 0x…] [--dev-buy …] # V3:接收地址那份税 50% 回购销毁,其余给你(或 --buyback-to 指定的地址)
81
+ gang buyback status|set|set-payee|apply --token 0x… [--pct 0-100] [--to 0x…] # 回购合约:比例(提高立即生效,下调 3 天后)、收款地址(立即生效)、待回购金额
82
82
  gang create --fair … [--shares <n>] --bond <数量> [--bond-hold …] --bond-days <7-90> # 打新:发币(含 dev 份额)→ 押金
83
83
  gang execute --request-id <id>
84
84
  gang tx --hash <0x..> [--testnet] # 解析 V2 / Soft 和 GangLaunchpad 的事件(GangLaunchpad 的带 units "raw",金额是 wei)
@@ -200,4 +200,4 @@ gang agents --window 30d --sort follow
200
200
 
201
201
  ## 版本
202
202
 
203
- `0.13.0` · [gangfun/cli](https://github.com/gangfun/cli) · push 到 `main` 自动发布到 [npm](https://www.npmjs.com/package/@gangfun/cli)
203
+ `0.14.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.13.0",
3
+ "version": "0.14.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/buyback.js CHANGED
@@ -4,9 +4,10 @@ import { walletFor } from './fair.js'
4
4
  import { parseNum, revertOf as revertIn, step } from './steps.js'
5
5
 
6
6
  /**
7
- * `gang buyback …` and `gang create … --buyback <pct>` — GangBuybackSplitter (dev 税按比例回购销毁): a V3 token's tax
8
- * recipient that splits each payment between a buy-back in the token's PancakeSwap pool, sent to 0xdead, and the dev.
9
- * GangBuybackSplitterFactory clones one per token for the dev (`create(bps, salt)`, at `predict(dev, salt)`) and has
7
+ * `gang buyback …` and `gang create … --buyback <pct> [--buyback-to <addr>]` — GangBuybackSplitter (dev 税按比例回购
8
+ * 销毁): a V3 token's tax recipient that splits each payment between a buy-back in the token's PancakeSwap pool, sent to
9
+ * 0xdead, and the dev's payee (the dev unless it names another address; v2 splitters only, `gang buyback set-payee`).
10
+ * GangBuybackSplitterFactory clones one per token for the dev (`create(bps, salt, payee)`, at `predict(dev, salt)`) and has
10
11
  * GangHandlerAdmin list it, so the dev names it as the recipient at create (launch.js does the three steps: clone →
11
12
  * create → bind). A dev who doesn't
12
13
  * want it leaves --buyback out: the tax goes to their own address as before.
@@ -15,13 +16,15 @@ import { parseNum, revertOf as revertIn, step } from './steps.js'
15
16
  * Env: GANG_SPLITTER_FACTORY / GANG_TESTNET_SPLITTER_FACTORY override the built-in factory addresses.
16
17
  */
17
18
 
18
- // BSC 56, 2026-10-28 (docs/MAINNET-BUYBACK-SPLITTER-2026-10-28.md); lists clones once the Safe ran its batch
19
- export const MAINNET_SPLITTER_FACTORY = '0x6bcd79206da85Aa0643Db2164Ab887b468618546'
20
- export const TESTNET_SPLITTER_FACTORY = '0x0Ff5C8801BdeaDac374fC14fEd6e7B31977c9DA1'
21
- export const BUYBACK_TYPE = 'buyback-burn-v1'
19
+ // BSC 56, factory v2 (payee; docs/MAINNET-BUYBACK-SPLITTER-2026-10-28.md). v1 was 0x6bcd…8546 (2-argument create)
20
+ export const MAINNET_SPLITTER_FACTORY = '0x93467Cb38B9Cb7f6EF3b67d2226Eb8b77ca58F2f'
21
+ export const TESTNET_SPLITTER_FACTORY = '0x08b9E2Cf5F666b55F262239b19e25de25b8ba87D'
22
+ /** The factory's clones; v1 (mainnet's first factory, 0x6bcd…8546) pays the dev, v2 its payee. */
23
+ export const BUYBACK_TYPE = 'buyback-burn-v2'
24
+ const BUYBACK_TYPES = ['buyback-burn-v1', BUYBACK_TYPE]
22
25
 
23
26
  export const FACTORY_ABI = parseAbi([
24
- 'function create(uint16 buybackBps, bytes32 salt) returns (address splitter)',
27
+ 'function create(uint16 buybackBps, bytes32 salt, address payee) returns (address splitter)',
25
28
  'function predict(address dev, bytes32 salt) view returns (address)',
26
29
  'function pad() view returns (address)',
27
30
  'error NotAgent()',
@@ -44,6 +47,8 @@ export const SPLITTER_ABI = parseAbi([
44
47
  'function setBuybackBps(uint16 newBps)',
45
48
  'function applyBuybackBps()',
46
49
  'function releaseDev() returns (uint256)',
50
+ 'function payee() view returns (address)',
51
+ 'function setPayee(address newPayee)',
47
52
  'error NotDev()',
48
53
  'error BadBps()',
49
54
  'error AlreadyBound()',
@@ -93,17 +98,22 @@ export async function splitterOf(read, addr) {
93
98
  if (!addr || addr === zeroAddress) return null
94
99
  let type
95
100
  try { type = await read(addr, SPLITTER_ABI, 'moduleType') } catch { return null }
96
- if (hexToString(type, { size: 32 }) !== BUYBACK_TYPE) return null
101
+ const moduleType = hexToString(type, { size: 32 }).replace(/\0+$/, '')
102
+ if (!BUYBACK_TYPES.includes(moduleType)) return null
97
103
  const [dev, token, bps, cut, left, unsplit, owed, burn] = await Promise.all(
98
104
  ['dev', 'token', 'buybackBps', 'pendingCut', 'buybackLeft', 'unsplit', 'devOwed', 'previewBurn'].map((f) => read(addr, SPLITTER_ABI, f)))
105
+ // v1 has no payee: it pays the dev
106
+ const hasPayee = moduleType !== 'buyback-burn-v1'
107
+ const payee = hasPayee ? await read(addr, SPLITTER_ABI, 'payee') : dev
108
+ const toDev = payee.toLowerCase() === dev.toLowerCase()
99
109
  // the pad takes 18-decimal quotes only
100
110
  const q = (x) => formatUnits(x, 18)
101
111
  return {
102
- splitter: addr, moduleType: BUYBACK_TYPE, dev, token: token === zeroAddress ? null : token, buybackPct: pct(bps), buybackBps: Number(bps),
112
+ splitter: addr, moduleType, dev, payee, payeeChangeable: hasPayee, token: token === zeroAddress ? null : token, buybackPct: pct(bps), buybackBps: Number(bps),
103
113
  pendingCut: cut[0] ? { toPct: pct(cut[1]), appliesFrom: iso(cut[2]), lapsesAfter: iso(Number(cut[2]) + 7 * 86400) } : null,
104
114
  buybackLeft: q(left), unsplit: q(unsplit), devOwed: q(owed),
105
115
  nextChunk: burn[0] ? { quoteIn: q(burn[1]), tokensBurned: formatUnits(burn[2], 18) } : null,
106
- note: `${pct(bps)}% of each tax payment to this recipient is bought back in the pool and burned (0xdead), the rest goes to the dev; a raise applies at once, a cut only 3 days after it is asked for`,
116
+ note: `${pct(bps)}% of each tax payment to this recipient is bought back in the pool and burned (0xdead), the rest goes to ${toDev ? 'the dev' : `the payee ${payee}`}; a raise applies at once, a cut only 3 days after it is asked for${hasPayee ? '; the dev can change the payee at once (gang buyback set-payee)' : ''}`,
107
117
  }
108
118
  }
109
119
 
@@ -125,8 +135,8 @@ export async function simulateCall(client, from, address, abi, functionName, arg
125
135
  }
126
136
  }
127
137
 
128
- const SUBS = ['status', 'set', 'apply', 'bind', 'release']
129
- const USAGE = 'usage: gang buyback <status|set|apply|bind|release> --token <addr> [--pct <0-100>] [--testnet] — see gang help'
138
+ const SUBS = ['status', 'set', 'set-payee', 'apply', 'bind', 'release']
139
+ const USAGE = 'usage: gang buyback <status|set|set-payee|apply|bind|release> --token <addr> [--pct <0-100>] [--to <addr>] [--testnet] — see gang help'
130
140
 
131
141
  /** `gang buyback <sub>`: the splitter of a V3 token (its tax recipient), found from --token. */
132
142
  export async function runBuyback(sub, { opt, flag, out, fail, summarize }) {
@@ -171,6 +181,18 @@ export async function runBuyback(sub, { opt, flag, out, fail, summarize }) {
171
181
  })
172
182
  }
173
183
 
184
+ if (sub === 'set-payee') {
185
+ if (!s.payeeChangeable) return fail('this splitter (buyback-burn-v1) has no payee: it pays the dev; only splitters from the current factory (v2) can name another address')
186
+ if (me().toLowerCase() !== s.dev.toLowerCase()) return fail('only the dev this splitter was made for can change its payee', { wallet: me(), dev: s.dev })
187
+ const to = opt('to')
188
+ if (!isAddress(to ?? '') || to === zeroAddress) fail('--to <0x…> required (checksummed or all lowercase): the address the dev\'s part goes to from now on', { got: to ?? null })
189
+ if (to.toLowerCase() === s.payee.toLowerCase()) return fail('that is the payee already', { payee: s.payee })
190
+ return send('setPayee', [to], {
191
+ step: 'set-payee', fromPayee: s.payee, toPayee: to,
192
+ note: 'applies at once (the dev\'s own share; holders are not affected). Quote that arrived before is split to the current payee first; what is owed goes to the new one',
193
+ })
194
+ }
195
+
174
196
  if (sub === 'apply') {
175
197
  if (!s.pendingCut) return fail(HINTS.NoProposal, { buybackPct: s.buybackPct })
176
198
  if (Date.parse(s.pendingCut.appliesFrom) > Date.now()) return fail(HINTS.NotDue, { appliesFrom: s.pendingCut.appliesFrom })
@@ -179,5 +201,5 @@ export async function runBuyback(sub, { opt, flag, out, fail, summarize }) {
179
201
 
180
202
  // release
181
203
  if (!(Number(s.devOwed) > 0)) return fail(HINTS.NothingOwed)
182
- return send('releaseDev', [], { step: 'release', amount: s.devOwed, note: 'anyone may; the dev gets what a failed push left owed' })
204
+ return send('releaseDev', [], { step: 'release', amount: s.devOwed, payee: s.payee, note: 'anyone may; the payee gets what a failed push left owed' })
183
205
  }
package/src/index.js CHANGED
@@ -284,9 +284,10 @@ graduated tokens only).
284
284
  gang create … --dev-buy <quote> [--bond <quote> [--bond-hold <tokens|N%|all>] --bond-days <7-90>]
285
285
  V3: create → the dev buys on the curve (--dev-buy, as gang buy) → bonds what it
286
286
  holds (--bond-hold, default all; gang bond post). Wrap / approve steps come in between
287
- gang create … --buy-tax <1-5> --sell-tax <1-5> --buyback <0-100> [--dev-buy … [--bond …]]
287
+ gang create … --buy-tax <1-5> --sell-tax <1-5> --buyback <0-100> [--buyback-to <addr>] [--dev-buy … [--bond …]]
288
288
  V3, taxed: the recipient's part of the tax is split, --buyback % bought back in the
289
- pool and burned (0xdead), the rest to you. Steps: clone your buy-back splitter
289
+ pool and burned (0xdead), the rest to you (or --buyback-to <addr>; changeable later
290
+ with gang buyback set-payee). Steps: clone your buy-back splitter
290
291
  (GangBuybackSplitterFactory; listed as a recipient in the same tx) → create with it as
291
292
  the recipient → bind → the rest of the launch. Without --buyback the tax goes to you
292
293
  gang create --fair … [--shares <n>] --bond <quote> [--bond-hold …] --bond-days <7-90>
@@ -347,12 +348,16 @@ BOND (押金承诺, GangBond; any GangLaunchpad token, from create on; GANG_BOND
347
348
  checked against X (--break-bond / --settle-first)
348
349
  BUYBACK (a V3 token whose recipient is a buy-back splitter; GANG_SPLITTER_FACTORY / GANG_TESTNET_SPLITTER_FACTORY):
349
350
  gang buyback status --token <addr> ratio, a cut asked for (applies from / lapses after), quote waiting to be bought
350
- back, owed to the dev, the next chunk (the keeper buys it back every few minutes)
351
+ back, the payee and what is owed to it, the next chunk (the keeper buys it back
352
+ every few minutes)
351
353
  gang buyback set --token <addr> --pct <0-100>
352
354
  dev only: a higher share applies at once; a lower one after a 3-day notice
355
+ gang buyback set-payee --token <addr> --to <addr>
356
+ dev only: the part not bought back goes to --to from now on (at once; splitters
357
+ from the current factory; the first mainnet ones, buyback-burn-v1, pay the dev)
353
358
  gang buyback apply --token <addr> anyone: apply a cut whose notice ran (within 7 days, or it lapses)
354
359
  gang buyback bind --token <addr> | gang buyback release --token <addr>
355
- anyone: bind the splitter to its token (the launch does it) / push the dev what a
360
+ anyone: bind the splitter to its token (the launch does it) / push the payee what a
356
361
  failed payment left owed. --testnet, --calldata, --from as in gang v3
357
362
  gang execute --request-id <id> broadcast a previewed call
358
363
  gang tx --hash <0x..> [--testnet] wait for receipt and decode Gang events: V2 / Soft / U / S, GangLaunchpad (V3 /
package/src/launch.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomBytes } from 'node:crypto'
2
2
  import { mkdirSync, readdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs'
3
3
  import { dirname, join } from 'node:path'
4
- import { createPublicClient, http, parseAbi, formatUnits, encodeFunctionData, zeroAddress } from 'viem'
4
+ import { createPublicClient, http, parseAbi, formatUnits, encodeFunctionData, isAddress, zeroAddress } from 'viem'
5
5
  import { DIR } from './notes.js'
6
6
  import { padNets, NOT_ON_MAINNET } from './gangpad.js'
7
7
  import { bondAddress, BOND_ABI } from './bond.js'
@@ -26,6 +26,7 @@ import { buybackBpsOf, FACTORY_ABI, notDeployed, simulateCall, SPLITTER_ABI, spl
26
26
  * predict(dev, salt), with a fresh salt per plan kept in it (so the address is known before the clone and never another
27
27
  * launch's), the create names it as the recipient, and a bind step follows the create. A launch keeps the mode it began
28
28
  * with: adding --buyback after the create (or dropping it before) is refused rather than starting over.
29
+ * --buyback-to <addr> names where the dev's part goes (default: the dev); the dev can change it later at once.
29
30
  */
30
31
 
31
32
  const LAUNCH_DIR = process.env.GANG_LAUNCH_DIR || join(dirname(DIR), 'launch')
@@ -39,7 +40,7 @@ const PAD_ABI = parseAbi([
39
40
  ])
40
41
  const ERC20_ABI = parseAbi(['function balanceOf(address) view returns (uint256)', 'function symbol() view returns (string)'])
41
42
  /** Flags only the chain reads; everything else goes to the step's own command. */
42
- export const LAUNCH_FLAGS = ['dev-buy', 'bond', 'bond-hold', 'bond-days', 'buyback', 'restart']
43
+ export const LAUNCH_FLAGS = ['dev-buy', 'bond', 'bond-hold', 'bond-days', 'buyback', 'buyback-to', 'restart']
43
44
  const NOTE_FLAGS = ['note', 'conf', 'reveal-after']
44
45
  /** `gang fair create --dev-buy`, with or without --bond (index.js stops the lone flag, runLaunch the chained one). */
45
46
  export const FAIR_DEV_BUY = 'a 打新 dev buys its shares in the create itself: use --shares <n> (not --dev-buy)'
@@ -108,6 +109,7 @@ export async function runLaunch(kind, { io, runV3, runFair, runBond, padNotes })
108
109
 
109
110
  // --buyback: a taxed V3 token whose recipient (the part left after holders) is the dev's splitter
110
111
  let buyback = null
112
+ if (flag('buyback-to') && !flag('buyback')) fail('--buyback-to <addr> goes with --buyback <pct>: it names where the part not bought back goes')
111
113
  if (flag('buyback')) {
112
114
  const zero = (f) => /^0+(\.0+)?$/.test(opt(f) ?? '')
113
115
  if (!flag('buy-tax') || !flag('sell-tax') || (zero('buy-tax') && zero('sell-tax'))) {
@@ -117,7 +119,12 @@ export async function runLaunch(kind, { io, runV3, runFair, runBond, padNotes })
117
119
  if (/^0*100(\.0+)?$/.test(opt('dividend', '0'))) fail('--dividend 100 leaves nothing for the recipient, so nothing to buy back: lower it or drop --buyback')
118
120
  const factory = splitterFactoryAddress(testnet)
119
121
  if (!factory) fail(notDeployed(testnet))
120
- buyback = { bps: buybackBpsOf(fail, opt('buyback')), factory }
122
+ let payee = null
123
+ if (flag('buyback-to')) {
124
+ payee = opt('buyback-to')
125
+ if (!isAddress(payee ?? '') || payee === zeroAddress) fail('--buyback-to must be a 0x address, checksummed or all lowercase (where the part not bought back goes; leave it out for your own wallet)', { got: payee ?? null })
126
+ }
127
+ buyback = { bps: buybackBpsOf(fail, opt('buyback')), factory, payee }
121
128
  }
122
129
 
123
130
  const client = createPublicClient({ chain: net.chain, transport: http(net.rpc) })
@@ -147,15 +154,16 @@ export async function runLaunch(kind, { io, runV3, runFair, runBond, padNotes })
147
154
  if (!plan?.salt) {
148
155
  const salt = `0x${randomBytes(32).toString('hex')}`
149
156
  const at = await read(buyback.factory, FACTORY_ABI, 'predict', [me, salt])
150
- const sim = await simulateCall(client, me, buyback.factory, FACTORY_ABI, 'create', [buyback.bps, salt])
157
+ const args = [buyback.bps, salt, buyback.payee ?? zeroAddress]
158
+ const sim = await simulateCall(client, me, buyback.factory, FACTORY_ABI, 'create', args)
151
159
  if (sim.failed) return out({ success: false, step: 'buyback-splitter', ...tag('buyback-splitter'), ...sim.failed })
152
160
  writePlan(key, { ...base, salt, splitter: at, factory: buyback.factory })
153
- const data = encodeFunctionData({ abi: FACTORY_ABI, functionName: 'create', args: [buyback.bps, salt] })
161
+ const data = encodeFunctionData({ abi: FACTORY_ABI, functionName: 'create', args })
154
162
  return out({
155
163
  ...step({ chainId: net.chainId }, { from: me, to: buyback.factory, data }, {
156
164
  step: 'buyback-splitter', chainId: Number(net.chainId), factory: buyback.factory, buybackPct: buyback.bps / 100,
157
- splitter: at,
158
- note: `clones your buy-back splitter (listed as a tax recipient in the same tx): ${buyback.bps / 100}% of the recipient's part is bought back and burned, the rest goes to you. A raise applies at once later, a cut only after a 3-day notice`,
165
+ splitter: at, payee: buyback.payee ?? me,
166
+ note: `clones your buy-back splitter (listed as a tax recipient in the same tx): ${buyback.bps / 100}% of the recipient's part is bought back and burned, the rest goes to ${buyback.payee ? `${buyback.payee} (--buyback-to)` : 'you'}. Later a raise applies at once, a cut only after a 3-day notice; the payee can be changed at once (gang buyback set-payee)`,
159
167
  }, flag('calldata'), io.summarize),
160
168
  ...tag('buyback-splitter', { splitter: at, next: `${rerun}: it then builds the create with the splitter as the recipient` }),
161
169
  })
@@ -173,6 +181,11 @@ export async function runLaunch(kind, { io, runV3, runFair, runBond, padNotes })
173
181
  if (s.buybackBps !== buyback.bps) {
174
182
  return fail(`this launch's splitter buys back ${s.buybackPct}%, not ${buyback.bps / 100}%: run it again with --buyback ${s.buybackPct}, or add --restart for a new splitter (gang buyback set changes it after the create)`, { splitter: plan.splitter })
175
183
  }
184
+ const wantPayee = (buyback.payee ?? me).toLowerCase()
185
+ if (s.payee.toLowerCase() !== wantPayee) {
186
+ const was = s.payee.toLowerCase() === me.toLowerCase() ? 'leave --buyback-to out' : `--buyback-to ${s.payee}`
187
+ return fail(`this launch's splitter pays ${s.payee}, not ${buyback.payee ?? me}: run it again with ${was}, or add --restart for a new splitter (gang buyback set-payee changes it after the create)`, { splitter: plan.splitter })
188
+ }
176
189
  }
177
190
 
178
191
  // ---- create