API Reference
TypeScript-native, viem-compatible, zero-config. Built for MegaETH.
v0.1.1Introduction
The problem: Every DeFi action on a standard EVM chain requires a separate transaction — approve, swap, stake, bridge. Each one is a separate wallet signature, a separate block confirmation, and a separate point of failure. If one step fails, the ones before it don't roll back. You're left with a stuck allowance, a half-executed position, or a drained account.
MegaFlow solves this by bundling any number of on-chain calls into a single atomic transaction through the on-chain MegaRouter contract. If any one call in the batch reverts, the entire transaction reverts — no partial state, no leaked approvals, no half-executed swaps.
Built for MegaETH's real-time layer: MegaFlow useseth_sendRawTransactionSync(EIP-7966), which means the RPC node holds the connection open until the transaction is confirmed on-chain — typically under 10ms. Your executeSync() call returns a mined receipt, not a pending hash.
Quick Start
Single import, zero boilerplate. As of v0.1.1,fromPrivateKey() handles viem account creation, WalletClient wiring, and chain config internally. The snippet below reads the current on-chain allowance, then batches a safe approval and swap into one atomic call.
Why safeApprove? USDT and some other tokens revert if you call approve() when the current allowance is non-zero. safeApprove() reads the current value and resets it to 0 first if needed — all inside the same atomic batch.
import { MegaFlowClient, MEGAETH_TOKENS, parseUnits } from '@megaflow-labs/sdk';
// One-liner setup — no viem/accounts needed
const client = MegaFlowClient.fromPrivateKey('0xYOUR_KEY');
const allowance = await client.getAllowance(MEGAETH_TOKENS.USDC, client.address!, DEX);
const { receipt } = await client
.batch()
.safeApprove(MEGAETH_TOKENS.USDC, DEX, parseUnits('100', 6), allowance)
.swapExactTokensForTokens({ ... })
.executeSync(); // ← instant receiptInstallation
npm install @megaflow-labs/sdkpnpm add @megaflow-labs/sdkyarn add @megaflow-labs/sdkPeer dependency: viem ^2.0 (already bundled via re-exports — separate install optional)
MegaFlowClient
The primary entry point. Manages chain config, wallet connection, and builder access.
MegaFlowClient.fromPrivateKey(key)v0.1.1Creates a fully connected client from a hex private key. No viem import needed.
MegaFlowClientMegaFlowClient.fromMnemonic(mnemonic)v0.1.1Creates a connected client from a BIP-39 mnemonic phrase.
MegaFlowClientnew MegaFlowClient(config?)Zero-config constructor. Uses MegaETH Mainnet and the deployed MegaRouter by default.
MegaFlowClient.connectWithAccount(account)Connects a viem Account and creates a WalletClient internally.
this.connect(walletClient)Connects an existing viem WalletClient directly.
this.addressgetterReturns the connected account address.
Address | undefined.getTokenBalance(token, address)Returns the ERC-20 balance for a given address.
Promise<bigint>.getAllowance(token, owner, spender)Returns the current ERC-20 allowance.
Promise<bigint>.getRouterInfo()Returns the MegaRouter flat fee and fee collector address.
Promise<RouterInfo>.batch()Returns a fresh MegaFlowBuilder bound to this client's config.
MegaFlowBuilderMegaFlowBuilder
Chainable builder returned by .batch(). Every method returns this for fluent chaining.
.approve(token, spender, amount)Standard ERC-20 approve.
this.safeApprove(token, spender, amount, current)USDT-safe: resets allowance to 0 first if current differs, then sets amount.
this.transfer(token, to, amount)ERC-20 token transfer.
this.transferFrom(token, from, to, amount)ERC-20 transferFrom.
this.multiTransfer(token, [{to, amount}])Batches multiple transfers of the same token.
this.swapExactTokensForTokens(params)Uniswap V2-compatible token→token swap.
this.swapExactETHForTokens(params)ETH→token swap.
this.swapExactTokensForETH(params)token→ETH swap.
this.approveAndSwap(params)Shorthand: .approve() + .swapExactTokensForTokens() combined.
this.kyberSwap(params, sender)Fetches best route from KyberSwap aggregator and adds the swap call.
Promise<this>.wrapETH(weth, amount)Deposits ETH into the WETH contract.
this.unwrapWETH(weth, amount)Withdraws WETH back to ETH.
this.transferNFT(nft, from, to, tokenId)ERC-721 safeTransferFrom.
this.approveNFT(nft, to, tokenId)ERC-721 single token approve.
this.setApprovalForAll(nft, operator, approved)ERC-721 operator approval.
this.simulate()Dry-run the batch. Returns success, gasEstimate, per-call results, revertReason.
Promise<SimulationResult>.execute(options?)Full flow: simulate → sign → broadcast → waitForReceipt.
Promise<ExecutionResult>.executeSync(options?)Uses eth_sendRawTransactionSync (EIP-7966). Instant receipt in one roundtrip.
Promise<SyncResult>.executeRealtime(options?)Uses realtime_sendRawTransaction endpoint.
Promise<SyncResult>.add(target, callData, value?)Raw call — lowest-level escape hatch.
this.sendETH(to, amount)Sends native ETH to an address.
this.getCalls()Returns a copy of the current call queue.
MegaCall[].getTotalValue()Sum of all ETH values in the batch.
bigint.summary()Human-readable description of the batch.
string.clear()Resets all queued calls.
this.isEmptyTrue when the call queue has no items.
booleanRecipes
Copy-paste patterns for the most common on-chain workflows. All examples use the v0.1.1 single-import — no viem config needed.
The most common DeFi flow — approval and swap bundled in one tx. If the swap reverts, the approval is also rolled back atomically.
import { MegaFlowClient, MEGAETH_TOKENS, parseUnits } from '@megaflow-labs/sdk';
const USDC = MEGAETH_TOKENS.USDC;
const WETH = MEGAETH_TOKENS.WETH;
const DEX = '0xYOUR_DEX_ROUTER';
const client = MegaFlowClient.fromPrivateKey(process.env.PRIVATE_KEY!);
// Read the current allowance before building the batch
const allowance = await client.getAllowance(USDC, client.address!, DEX);
const amount = parseUnits('100', 6); // 100 USDC
const { receipt } = await client
.batch()
.safeApprove(USDC, DEX, amount, allowance) // reset+approve atomically
.swapExactTokensForTokens({
amountIn: amount, amountOutMin: 0n,
path: [USDC, WETH], to: client.address!,
deadline: BigInt(Date.now() + 300_000),
})
.executeSync(); // ← single tx, instant receipt <10ms
console.log('Mined:', receipt.transactionHash);Send USDC, WETH, and native ETH to different recipients — all in a single atomic call. All succeed or all revert.
import { MegaFlowClient, MEGAETH_TOKENS, parseUnits, parseEther } from '@megaflow-labs/sdk';
const client = MegaFlowClient.fromPrivateKey(key);
await client.batch()
.transfer(MEGAETH_TOKENS.USDC, '0xAlice', parseUnits('50', 6))
.transfer(MEGAETH_TOKENS.WETH, '0xBob', parseEther('0.5'))
.sendETH('0xCarol', parseEther('0.1'))
.executeSync();kyberSwap() is async — it fetches the optimal route from the aggregator API and appends the calldata to your batch. Combine with approve() for a zero-slippage atomic bundle.
import { MegaFlowClient, MEGAETH_TOKENS, parseUnits } from '@megaflow-labs/sdk';
const client = MegaFlowClient.fromPrivateKey(key);
const amount = parseUnits('500', 6); // 500 USDC
// kyberSwap() fetches the best route from the aggregator API
const builder = await client
.batch()
.approve(MEGAETH_TOKENS.USDC, '0xKyberRouter', amount)
.kyberSwap({
tokenIn: MEGAETH_TOKENS.USDC,
tokenOut: MEGAETH_TOKENS.WETH,
amountIn: amount,
slippage: 50, // 0.5%
}, client.address!);
await builder.executeSync();Dry-run the full batch first — no gas consumed, no on-chain state change. Inspect per-call results and revert reasons, then execute only if it passes.
import { MegaFlowClient, MEGAETH_TOKENS, parseUnits } from '@megaflow-labs/sdk';
const client = MegaFlowClient.fromPrivateKey(key);
const builder = client.batch()
.approve(tokenA, spender, amount)
.swapExactTokensForTokens({ ...swapParams });
// 1. Dry-run — zero gas, zero state change
const sim = await builder.simulate();
if (!sim.success) {
console.error('Revert reason:', sim.revertReason);
console.error('Failed at call index:', sim.failedCallIndex);
return;
}
// 2. Simulation passed — safe to execute
console.log('Estimated gas:', sim.gasEstimate);
const { receipt } = await builder.executeSync();Error Codes
EMPTY_BATCHNo calls queued before execution.
WALLET_NOT_CONNECTED.connect() or .connectWithAccount() not called.
SIMULATION_FAILEDDry-run reverted — check revertReason and failedCallIndex.
EXECUTION_FAILEDOn-chain transaction reverted.
INVALID_TARGETA call targets the zero address or invalid contract.
USER_REJECTEDUser rejected the transaction in their wallet.
INSUFFICIENT_ETHETH value sent is less than the sum required by all calls.
KYBERSWAP_ERRORKyberSwap aggregator API returned an error.
Need help?
Open an issue or start a discussion on GitHub.