Skip to content

Buy and burn on a schedule

Tested on BSC testnet before every release

This is an example. Every value in it (names, amounts, addresses) is there to show you how; change any of them to suit you. It’s recipe-burn-schedule.mjs, exactly as our tests run it on testnet. Point it at testnet with MM_API, or leave it for mainnet.

recipe-burn-schedule.mjs
// Buy-and-burn on a schedule: every so often, buy a fixed amount of a token and
// send what you bought to the dead address, for ever. Each round is two
// transactions you can show people: the buy, and the burn.
// PRIVATE_KEY=0x… TOKEN=0x… node recipe-burn-schedule.mjs
//
// Every setting has a cap you choose on purpose:
// SPEND=0.01 BNB per round
// EVERY_MINUTES=60 minutes between rounds
// MAX_TOTAL=0.1 BNB across the whole run; it stops after this
// RUNS= stop after this many rounds (default: until MAX_TOTAL)
import { MarketMayhem } from '@marketmayhem/sdk';
import { Contract, JsonRpcProvider, Wallet, formatUnits } from 'ethers';
const DEAD = '0x000000000000000000000000000000000000dEaD';
const token = process.env.TOKEN;
const spend = Number(process.env.SPEND ?? '0.01');
const everyMs = Number(process.env.EVERY_MINUTES ?? '60') * 60_000;
const maxTotal = Number(process.env.MAX_TOTAL ?? '0.1');
const runs = process.env.RUNS ? Number(process.env.RUNS) : Infinity;
if (!token || !(spend > 0) || !(maxTotal >= spend)) throw new Error('Set TOKEN, and SPEND no bigger than MAX_TOTAL.');
const mm = MarketMayhem.fromPrivateKey(process.env.PRIVATE_KEY, { api: process.env.MM_API });
const { chainId } = await mm.settings();
const rpc = chainId === 56 ? 'https://bsc-dataseed.bnbchain.org' : 'https://bsc-testnet-rpc.publicnode.com';
const wallet = new Wallet(process.env.PRIVATE_KEY, new JsonRpcProvider(rpc, chainId));
const erc20 = new Contract(token, ['function balanceOf(address) view returns (uint256)', 'function transfer(address, uint256) returns (bool)', 'function decimals() view returns (uint8)'], wallet);
const decimals = await erc20.decimals();
let spent = 0;
let round = 0;
const burned = [];
while (round < runs && spent + spend <= maxTotal + 1e-12) {
round += 1;
// Burn exactly what this round bought: the balance before and after, not the whole wallet.
const before = await erc20.balanceOf(wallet.address);
const buy = await mm.buy(token, { spend: String(spend) });
const bought = (await erc20.balanceOf(wallet.address)) - before;
const burn = await (await erc20.transfer(DEAD, bought)).wait();
spent += spend;
burned.push({ buy: buy.hash, burn: burn.hash });
console.log(`round ${round}: bought ${formatUnits(bought, decimals)} for ${spend} BNB (${buy.hash}), burned them (${burn.hash})`);
if (round < runs && spent + spend <= maxTotal + 1e-12) await new Promise((r) => setTimeout(r, everyMs));
}
console.log(`done: ${round} round(s), ${spent} BNB spent`);
console.log('RESULT', JSON.stringify({ rounds: round, spent, burned }));