Skip to content

Buy a token

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 buy.mjs, exactly as our tests run it on testnet. Point it at testnet with MM_API, or leave it for mainnet.

buy.mjs
// Buy a token with BNB, from your own wallet. The API builds and simulates the
// transaction; your key signs it here and never leaves this process.
// PRIVATE_KEY=0x… TOKEN=0x… node buy.mjs
import { JsonRpcProvider, Wallet } from 'ethers';
const API = process.env.MM_API ?? 'https://marketmayhem.co/api/v1';
const token = process.env.TOKEN;
const spend = process.env.AMOUNT ?? '0.001';
// The network, from the API: never hard-code it.
const settings = await (await fetch(`${API}/settings`)).json();
const rpc = settings.chainId === 56 ? 'https://bsc-dataseed.bnbchain.org' : 'https://bsc-testnet-rpc.publicnode.com';
const wallet = new Wallet(process.env.PRIVATE_KEY, new JsonRpcProvider(rpc, settings.chainId));
async function build(path, body) {
const res = await fetch(`${API}${path}`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });
const json = await res.json();
if (!res.ok) throw new Error(`${json.error.code}: ${json.error.message} ${json.error.fix ?? ''}`);
return json;
}
async function send(tx) {
const sent = await wallet.sendTransaction({ to: tx.to, data: tx.data, value: BigInt(tx.value), gasLimit: tx.gas ? BigInt(tx.gas) : undefined });
const receipt = await sent.wait();
if (receipt.status !== 1) throw new Error(`reverted: ${sent.hash}`);
return sent.hash;
}
async function waitUntilIndexed(hash) {
for (;;) {
const { status } = await (await fetch(`${API}/tx/${hash}`)).json();
if (status === 'indexed' || status === 'failed') return status;
await new Promise((r) => setTimeout(r, 2000));
}
}
const request = { wallet: wallet.address, token, amount: spend, slippageBps: 100 };
let built = await build('/build/buy', request);
// Buying a BNB-paired token needs no approval. A token-paired one may: send the
// one-time steps, then build again so the trade itself is simulated.
while (built.requires.length) {
for (const step of built.requires) await send(step.tx);
built = await build('/build/buy', request);
}
console.log(built.explain);
const hash = await send(built.tx);
const status = await waitUntilIndexed(hash);
console.log(`${status}: ${hash}`);
console.log('RESULT', JSON.stringify({ hash, status }));