The broader 9mm Pro suite became Watergun. Read the story.
Watergun Docs

Developer Integration

Watergun developer reference for GraphQL subgraphs, contract interfaces, and routing primitives.

Everything you need to quote prices, execute swaps, manage LP positions, and build on the Watergun DEX. For $9MM token-specific information and updates, visit 9mm.pro. The former tokenomics, claim, and holder revenue-sharing programs are sunset.

Watergun's DEX and routing interfaces follow familiar Uniswap V2 / V3 and 0x patterns. Verify compatibility against the specific deployed contract or API before integrating. The PulseChain DEX remains with 9mm Pro, not Watergun.

Stack Overview

Watergun hosted services and on-chain integration stack
    • Your appReads indexed data and calls on-chain contracts.
    • Hosted servicesGraphQL subgraphs, Watergun Swap routing API, and block explorer data.
    • On-chain primitivesV2, V3, SmartRouter, UniversalRouter, Permit2, and StableSwap.
LayerWhat it gives youWhere
SubgraphsHistorical pool / swap / LP event data, GraphQLdeployments repo
Block explorerTransaction lookups, contract verification9mm-scan on GitHub
V2 contractsConstant-product AMM (Factory + Router)On-chain
V3 contractsConcentrated liquidity (Factory + Quoter + SmartRouter + NFPM)On-chain
V4 / Universal RouterUnified routing, Permit2 approvalsOn-chain
Watergun Swap aggregatorMulti-DEX best-execution routingswap.watergun.pro

GraphQL Subgraphs

Per-chain subgraphs index V2 and V3 pools, swaps, liquidity events, and historical metrics. We run our own indexer stack — 9mm-exchange/graph-node — and publish subgraph definitions at 9mm-exchange/subgraphs.

Endpoint URLs

Per-chain endpoints are published in our deployments repo as JSON files (kept current alongside contract addresses):

Schema

The V2 and V3 subgraphs expose the standard Uniswap-compatible entities — Factory, Pool / Pair, Token, Swap, Mint, Burn, Bundle, PoolDayData, TokenDayData, and so on. If you've queried Uniswap or PancakeSwap subgraphs before, the same queries will work here.

Common Queries

{
  pools(first: 20, orderBy: totalValueLockedUSD, orderDirection: desc) {
    id
    token0 { symbol name decimals }
    token1 { symbol name decimals }
    feeTier
    liquidity
    totalValueLockedUSD
    volumeUSD
  }
}

Contract Reference

V2 — Constant Product AMM

The V2 layer is the simplest — a Factory that creates Pair contracts (each is a liquidity pool), and a Router that batches swap / add / remove actions into a single call.

Prop

Type

Key factory method:

function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);

Key router methods:

function getAmountsOut(uint amountIn, address[] calldata path)
    external view returns (uint[] memory amounts);

function swapExactTokensForTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external returns (uint[] memory amounts);

function addLiquidity(
    address tokenA,
    address tokenB,
    uint amountADesired,
    uint amountBDesired,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);

Quote example:

// Get USDC output for 1 WETH
IV2Router router = IV2Router(V2_ROUTER_ADDRESS);
address[] memory path = new address[](2);
path[0] = WETH;
path[1] = USDC;
uint[] memory amounts = router.getAmountsOut(1 ether, path);
// amounts[1] = USDC you'd receive

V3 — Concentrated Liquidity

V3 pools take three parameters: token0, token1, and a fee tier. The Watergun V3 fee tiers documented here are:

Fee tierfee (uint24)Typical use
0.01%100Stablecoin pairs
0.05%500Low-volatility pairs
0.25%2500Standard pairs
1%10000Volatile / exotic
2%20000Highly volatile

Key V3 contracts:

Prop

Type

Quote a single-pool V3 swap (off-chain):

IQuoterV2 quoter = IQuoterV2(QUOTER_V2_ADDRESS);

(uint256 amountOut, , , ) = quoter.quoteExactInputSingle(
  IQuoterV2.QuoteExactInputSingleParams({
    tokenIn:          WETH,
    tokenOut:         USDC,
    amountIn:         1 ether,
    fee:              2500,        // 0.25% tier
    sqrtPriceLimitX96: 0
  })
);
ethers.js quote
import { ethers } from 'ethers';
import QuoterAbi from './abi/QuoterV2.json';

const quoter = new ethers.Contract(QUOTER_V2_ADDRESS, QuoterAbi, provider);

const params = {
  tokenIn: WETH,
  tokenOut: USDC,
  amountIn: ethers.parseEther('1'),
  fee: 2500,
  sqrtPriceLimitX96: 0n,
};

const [amountOut] = await quoter.quoteExactInputSingle.staticCall(params);
console.log('1 WETH →', ethers.formatUnits(amountOut, 6), 'USDC');

Execute a V3 swap via SwapRouter:

ISwapRouter router = ISwapRouter(SWAP_ROUTER_ADDRESS);

IERC20(WETH).approve(SWAP_ROUTER_ADDRESS, 1 ether);

router.exactInputSingle(
  ISwapRouter.ExactInputSingleParams({
    tokenIn:          WETH,
    tokenOut:         USDC,
    fee:              2500,
    recipient:        msg.sender,
    deadline:         block.timestamp + 60,
    amountIn:         1 ether,
    amountOutMinimum: minUSDCOut,
    sqrtPriceLimitX96: 0
  })
);

SmartRouter — Mixed V2/V3 Routing

For multi-hop routes that may span V2 and V3 pools, use SmartRouter. It accepts encoded paths and picks the optimal execution strategy across both versions in a single transaction.

// Multi-hop V3 encoded path: tokenIn -> fee -> tokenMid -> fee -> tokenOut
bytes memory path = abi.encodePacked(
  WETH, uint24(500), USDC, uint24(100), USDT
);

ISmartRouter(SMART_ROUTER_ADDRESS).exactInput(
  ISmartRouter.ExactInputParams({
    path: path,
    recipient: msg.sender,
    deadline: block.timestamp + 60,
    amountIn: 1 ether,
    amountOutMinimum: minOut
  })
);

SmartRouter addresses per chain live in Deployments.

V4 — UniversalRouter + Permit2

V4 deployments (BNB Chain and Sonic at the time of writing) use the UniversalRouter plus Permit2 for gasless approvals. The router accepts a command-encoded payload and executes arbitrary sequences of V2 / V3 swaps, LP actions, and Permit2 approvals in a single transaction.

The command format is compatible with Uniswap's Universal Router spec — check the source repos for the full command set and encoding helpers.

StableSwap (BNB Chain)

BNB Chain additionally deploys a StableSwap layer for pegged pairs (stablecoin-to-stablecoin, LSTs, etc.). StableSwap uses a different AMM curve optimized for low-slippage trades between similarly-priced assets. Contracts:

  • LPFactory, StableFactory, SwapTwoPoolDeployer, SwapThreePoolDeployer, TwoPoolInfo, ThreePoolInfo, StableInfo

Addresses: Deployments → BNB Chain.


Watergun Swap API

The Watergun Swap interface is at swap.watergun.pro; the former 9x product name and 9x.9mm.pro address are retired. Do not rely on older screenshots or source counts as a current quote or venue list.

The Watergun Swap aggregator routes trades across available liquidity sources, including external venues. On PulseChain, the 9mm Pro DEX is a separate venue that Watergun Swap may route through. The API follows 0x-v1 conventions; verify individual response and approval behavior before treating it as a drop-in replacement.

Base URLs (per chain)

ChainBase URL
PulseChain (default)https://api.9mm.pro
Basehttps://api-base.9mm.pro
Sonichttps://api-sonic.9mm.pro
Additional chainsPublished in the deployments repo as new chains come online

There is also a general-purpose price endpoint at https://price-api.9mm.pro/api/price used by the Watergun Swap front-end for passive price polling.

Endpoints

All endpoints mirror the 0x Protocol Swap API v1 — same routes, same query-parameter names, same response shape.

MethodPathPurpose
GET/swap/v1/sourcesList every liquidity source the aggregator routes across
GET/swap/v1/priceIndicative price — no calldata, no approval prompts, safe for polling
GET/swap/v1/quoteExecutable quote with to + data calldata ready for eth_sendTransaction

The query-parameter and response schema is identical to 0x v1. The historical 0x v1 Swap API reference — parameter names, allowed values, error codes — is the best external spec for Watergun Swap. The 0x-v1-era documentation is maintained (archived) at docs.0x.org and in the 0xProject/0x-api repository.

Query Parameters

ParamRequiredTypeNotes
sellTokenyesaddressERC-20 contract of the token you're selling
buyTokenyesaddressERC-20 contract of the token you're buying
sellAmountone ofuintAmount to sell, in base units (wei / smallest unit)
buyAmountone ofuintAmount to receive, in base units
slippagePercentagenofloatE.g. 0.01 for 1% — defaults to 1% if omitted
takerAddressnoaddressRequired if you want gas estimation in the response
excludedSourcesnoCSVComma-separated list from /swap/v1/sources
includedSourcesnoCSVForce routing only through specific sources

Exactly one of sellAmount or buyAmount must be provided (just like 0x v1).

Request Patterns

Get the liquidity-source list — scripts your aggregator can use to track what Watergun Swap routes through:

curl 'https://api.9mm.pro/swap/v1/sources'

The response lists currently available sources. Do not hardcode a snapshot of venue names or assume a source is available on every network.

For an indicative price, request /swap/v1/price with the selected network's sellToken, buyToken, and either sellAmount or buyAmount. For an executable quote, request /swap/v1/quote with the same token parameters and a real takerAddress. Inspect the returned to, data, value, allowanceTarget, and gas estimate before presenting a transaction to the user. For $9MM token-specific addresses or trading guidance, visit 9mm.pro.

JavaScript Example

async function quoteSwap({ sellToken, buyToken, sellAmount, taker }) {
  const params = new URLSearchParams({
    sellToken, buyToken, sellAmount, takerAddress: taker
  });
  const r = await fetch(`https://api.9mm.pro/swap/v1/quote?${params}`);
  if (!r.ok) throw new Error(`Watergun Swap error: ${r.status}`);
  return r.json();
}

// Pass verified token addresses and an actual wallet address for the selected network.
// Review the returned allowanceTarget and transaction data before signing.

Rate Limits

No published rate limit. The API is aggressively cached and serves cheaply — but please self-throttle. Sustained high-volume traffic from a single IP will be rate-limited.

0x v1 Compatibility Notes

Because Watergun Swap is a 0x Protocol v1 fork:

  • Drop-in for 0x v1 clients — swap your base URL from api.0x.org to api.9mm.pro and existing 0x v1 integrations work unchanged
  • Quote / price response schemas are identical to 0x v1
  • Source naming matches 0x conventions (e.g., Uniswap_V3, SushiSwap, Balancer_V2)
  • No Permit2 or AllowanceHolder patterns — those are 0x v2 features. Watergun Swap uses the v1 approval flow: approve allowanceTarget, then execute the quote
  • No gasless / meta-transaction API — Watergun Swap v1 is direct-execution only

The archived 0x v1 documentation (docs.0x.org and the 0xProject/0x-api repo) is an authoritative external reference for every parameter and error code — Watergun Swap implements the same contract.

Integrated Liquidity Sources

Source availability changes by network and time. Query /swap/v1/sources against the relevant API base URL for the current list. NineMM_V2 and NineMM_V3, if returned for PulseChain, refer to the 9mm Pro PulseChain DEX rather than a Watergun DEX deployment.


Common Integration Patterns

Discover pools

Use the V3 Factory's getPool(tokenA, tokenB, fee) to find a specific pool, or subscribe to PoolCreated events via subgraph. For V2, use Factory.getPair(tokenA, tokenB).

Quote a swap

For V2: call Router.getAmountsOut(amountIn, path) — free and always works.

For V3: QuoterV2.quoteExactInputSingle(...) in a staticCall (it mutates state internally; never send it as a real transaction).

For optimal routing: hit Watergun Swap for aggregated quotes across our own pools and external sources.

Approve tokens

Call IERC20(token).approve(router, amount) before any swap. On V4, use Permit2 to skip approvals via a signature — one-time permit, infinite reuse.

Execute

Send the swap transaction. Always include a deadline (e.g., block.timestamp + 60 for 1-minute expiry) and amountOutMinimum (slippage protection). A swap with 0 slippage protection is a free lunch for MEV bots.

Watch results

Subscribe to the pool's Swap event, or query the subgraph's swaps entity. The swap hash is returned by the transaction — surface it to your user with a link to 9mm-scan or the chain's canonical explorer.

Tips and Gotchas


Useful Repositories

Help & Feedback

If you ship a Watergun integration, let us know — we'll add you to Partners & Integrations. For $9MM token integrations, start at 9mm.pro.

On this page