@gangfun/cli 0.12.0 → 0.13.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 +18 -1
- package/README.zh-CN.md +18 -1
- package/package.json +1 -1
- package/src/bond.js +564 -0
- package/src/buyback.js +183 -0
- package/src/fair.js +8 -1
- package/src/index.js +80 -1
- package/src/launch.js +284 -0
- package/src/pool.js +10 -1
- package/src/v3.js +11 -2
package/src/pool.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseAbi, encodeFunctionData, formatUnits, parseUnits, zeroAddress } from 'viem'
|
|
2
2
|
import { decimalsOf, isMissingFunction, poolSellQuote, ROUTER_ABI, routerDeadline, step, units, GAS_RESERVE } from './steps.js'
|
|
3
|
+
import { bondGuard } from './bond.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* PancakeSwap (V2 pool) buys and sells of a graduated / launched token through GangRouter — V3 and 打新 tokens
|
|
@@ -12,6 +13,7 @@ import { decimalsOf, isMissingFunction, poolSellQuote, ROUTER_ABI, routerDeadlin
|
|
|
12
13
|
* Minimums: a buy = Pancake getAmountsOut less the token's buy tax, less --slippage; a sell = the tax handler's
|
|
13
14
|
* previewSellNextBlock (the sell tax and the chunk of held tax it sells first included, as of the next block), or
|
|
14
15
|
* getAmountsOut less the sell tax when there is no handler quote (V2 tokens, untaxed V3), less --slippage.
|
|
16
|
+
* A sell with `p.bond` ({ testnet, breakBond, settleFirst }) is checked against the seller's GangBond first (bondGuard).
|
|
15
17
|
*/
|
|
16
18
|
|
|
17
19
|
// Pancake V2 routers: a GangRouter address must never be one of these (they would take an approve and swap for anyone).
|
|
@@ -185,7 +187,7 @@ async function build(ctx, p, { rawOnly, summarize, revertOf }) {
|
|
|
185
187
|
const quoteSymbol = (await symbolOf(ctx, quote)) || quote
|
|
186
188
|
const deadline = routerDeadline()
|
|
187
189
|
const taxPct = (bps) => (bps || 0) / 100
|
|
188
|
-
let call, probe, value = 0n, pull = null, fields
|
|
190
|
+
let call, probe, value = 0n, pull = null, fields, guard = null
|
|
189
191
|
try {
|
|
190
192
|
if (side === 'buy') {
|
|
191
193
|
const payBnb = !!p.payBnb
|
|
@@ -226,6 +228,12 @@ async function build(ctx, p, { rawOnly, summarize, revertOf }) {
|
|
|
226
228
|
const amount = p.all ? bal : parseUnits(p.amount, 18)
|
|
227
229
|
if (amount === 0n) throw new PoolError(`--amount ${p.amount} rounds to 0 tokens`)
|
|
228
230
|
if (amount > bal) return failOut({ step: 'pool-sell', error: 'amount exceeds balance', balance: formatUnits(bal, 18) })
|
|
231
|
+
// the creator's own bond: refuse a sell that breaks it (unless --break-bond), settle first past the deadline
|
|
232
|
+
if (p.bond) {
|
|
233
|
+
guard = await bondGuard(ctx, { token, me, amount, ...p.bond }, rawOnly, summarize)
|
|
234
|
+
if (guard?.refuse) return failOut({ step: 'pool-sell', wallet: me, ...guard.refuse })
|
|
235
|
+
if (guard?.settleStep) return guard.settleStep
|
|
236
|
+
}
|
|
229
237
|
const taxed = (p.sellTaxBps || 0) > 0
|
|
230
238
|
let quoteOut, quotedWith
|
|
231
239
|
if (taxed && p.handler) {
|
|
@@ -254,6 +262,7 @@ async function build(ctx, p, { rawOnly, summarize, revertOf }) {
|
|
|
254
262
|
deadline: Number(deadline), quotedWith,
|
|
255
263
|
...(toBnb && !quoteWbnb && { expectQuoteBeforeBnb: await units(ctx, quote, quoteOut) }),
|
|
256
264
|
gas: p.swapBackGas ? POOL_SELL_GAS_NOTE : 'let the wallet estimate gas',
|
|
265
|
+
...guard?.info,
|
|
257
266
|
note: quotedWith === 'getAmountsOut'
|
|
258
267
|
? `minOut = getAmountsOut of the amount less the ${taxPct(p.sellTaxBps)}% sell tax${toBnb && !quoteWbnb ? ' (then quote → WBNB)' : ''}, less --slippage (the sell reverts below it)`
|
|
259
268
|
: `minOut = the tax handler's ${quotedWith} (sell tax and the chunk of held tax sold first included, as of the next block)${toBnb && !quoteWbnb ? ', then getAmountsOut quote → WBNB' : ''}, less --slippage (the sell reverts below it)`,
|
package/src/v3.js
CHANGED
|
@@ -5,6 +5,8 @@ import { UA } from './version.js'
|
|
|
5
5
|
import { walletFor } from './fair.js'
|
|
6
6
|
import { MERGED_ERRORS_ABI, MERGED_HINTS, NOT_ON_MAINNET, notThisKind, padNets } from './gangpad.js'
|
|
7
7
|
import { poolPayBnb, poolTrade } from './pool.js'
|
|
8
|
+
import { bondGuard } from './bond.js'
|
|
9
|
+
import { splitterOf } from './buyback.js'
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* `gang v3 …` — LaunchpadV3 (tax recipient): a token with its own buy / sell tax (1–5% each), a dividend share and a
|
|
@@ -274,7 +276,9 @@ export async function runV3(sub, { opt, flag, out, fail, summarize, resolveLogo,
|
|
|
274
276
|
const taxNote = c.buyTaxPct > 0 || c.sellTaxPct > 0
|
|
275
277
|
? `buy ${c.buyTaxPct}% / sell ${c.sellTaxPct}% tax only in the PancakeSwap pool after graduation (${fees.platformTaxPct}% of volume to the platform, then ${c.dividendPct}% of the rest to holders, the remainder to the recipient); curve trades pay only the ${fees.curveFeePct}% fee, no tax`
|
|
276
278
|
: `untaxed; curve trades pay the ${fees.curveFeePct}% fee`
|
|
277
|
-
|
|
279
|
+
// a recipient that is the dev's buy-back splitter: its ratio and what waits to be bought back
|
|
280
|
+
const buyback = c.recipient && !c.recipientIsCreator ? await splitterOf(ctx.read, c.recipient) : null
|
|
281
|
+
return out({ success: true, chainId: Number(ctx.chainId), ...fees, ...pub, taxNote, ...(swapBack && { swapBack }), ...(buyback && { buyback }) })
|
|
278
282
|
}
|
|
279
283
|
|
|
280
284
|
if (sub === 'status') {
|
|
@@ -472,6 +476,7 @@ export async function runV3(sub, { opt, flag, out, fail, summarize, resolveLogo,
|
|
|
472
476
|
side: 'sell', token, quote: c.quote, me, amount: flag('all') ? null : parseAmount(fail, 'amount', opt('amount')), all: flag('all'),
|
|
473
477
|
slippage, buyTaxBps: Math.round(c.buyTaxPct * 100), sellTaxBps: Math.round(c.sellTaxPct * 100), handler: c.taxHandler,
|
|
474
478
|
swapBackGas: c.sellTaxPct > 0, toBnb: flag('to-bnb'), base: { kind: 'v3', pair: c.pair, ...notes.pool },
|
|
479
|
+
bond: { testnet, breakBond: flag('break-bond'), settleFirst: flag('settle-first') },
|
|
475
480
|
}, { rawOnly, summarize, revertOf }))
|
|
476
481
|
}
|
|
477
482
|
if (flag('all')) return fail('--all needs a wallet (or --from <addr>) whose balance can be read', { pair: c.pair })
|
|
@@ -493,6 +498,9 @@ export async function runV3(sub, { opt, flag, out, fail, summarize, resolveLogo,
|
|
|
493
498
|
if (bal === 0n) fail('no balance to sell')
|
|
494
499
|
const amount = flag('all') ? bal : parseUnits(parseAmount(fail, 'amount', opt('amount')), 18)
|
|
495
500
|
if (amount > bal) fail('amount exceeds balance', { balance: formatUnits(bal, 18) })
|
|
501
|
+
// a bond posted on the curve already binds: a creator's curve sell below X breaks it
|
|
502
|
+
const guard = await bondGuard(ctx, { token, me, amount, testnet, breakBond: flag('break-bond'), settleFirst: flag('settle-first') }, rawOnly, summarize)
|
|
503
|
+
if (guard?.refuse) return out({ success: false, step: 'sell', wallet: me, ...guard.refuse })
|
|
496
504
|
const pre = await fundingStep(ctx, me, token, amount, c.quoteSymbol, 'approve', rawOnly, summarize)
|
|
497
505
|
if (pre) return out(pre.success ? { ...pre, ...notes.skipped() } : pre)
|
|
498
506
|
const sim = await simulate(ctx, me, ctx.pad, PAD_ABI, 'sell', [token, amount, 0n])
|
|
@@ -502,7 +510,8 @@ export async function runV3(sub, { opt, flag, out, fail, summarize, resolveLogo,
|
|
|
502
510
|
step: 'sell', chainId: Number(ctx.chainId), token, amount: formatUnits(amount, 18), quote: c.quoteSymbol,
|
|
503
511
|
expectOut: await units(ctx, c.quote, sim.result), minOut: await units(ctx, c.quote, minOut), curveTaxPct: 0,
|
|
504
512
|
...(c.sellTaxPct > 0 && { poolSellTaxPct: c.sellTaxPct }),
|
|
505
|
-
curveFeePct: (await feesOf(ctx)).curveFeePct,
|
|
513
|
+
curveFeePct: (await feesOf(ctx)).curveFeePct, ...guard?.info,
|
|
514
|
+
note: 'expectOut is after the 1% curve fee only (no tax on the curve; the sell tax applies only in the pool after graduation)',
|
|
506
515
|
}, 'sell'))
|
|
507
516
|
}
|
|
508
517
|
|