@nradko/metric-omm-sdk
v0.0.14
Published
TypeScript SDK for interacting with Metric AMM contracts
Maintainers
Readme
@nradko/metric-omm-sdk
TypeScript SDK for interacting with Metric OMM AMM contracts using viem.
Installation
npm install @nradko/metric-omm-sdk viemQuick Start
import { getSlot0, ChainId, ADDRESSES } from "@nradko/metric-omm-sdk";
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
const publicClient = createPublicClient({
chain: mainnet,
transport: http(),
});
const addresses = ADDRESSES[ChainId.ETHEREUM];
const slot0 = await getSlot0(publicClient, addresses.stateView, poolAddress);
console.log(`Current Bin: ${slot0.curBinIdx}`);Deployed Contract Addresses
Factory, PoolDeployer, and StateView share the same addresses across all chains (CREATE2). Router addresses differ per chain due to different WETH constructor arguments.
| Contract | All Chains (CREATE2) |
| ---------------------- | -------------------------------------------- |
| MetricOmmPoolFactory | 0xe22F9fc0f04486dE25ed6CF1800a4a47aFD82e0C |
| MetricOmmPoolDeployer | 0x0f732971a3503afee276782173170D1F1154d4c1 |
| MetricOmmPoolStateView | 0xe6b102a2aea65b9b59e4F8B86B38E221886675A8 |
| Chain | MetricOmmSwapRouter |
| --------- | -------------------------------------------- |
| Ethereum | 0xcB41C10c6414aCbea022c7662df4005dd8FBEF91 |
| Base | 0xA6A16C00B7E9DBE1D54acEd7d6FE264fc4732eaF |
| Arbitrum | 0x82A562fD9F02d4346B95D3a2a501411979C8F920 |
| Avalanche | 0x5C1e08DF74a3457648A4C4dc5DC0DE497284c53C |
| BNB | 0xa9a63266bB70eb3419C34C245F4318983f325Bbd |
| Polygon | 0x976c26402E1EC10454c5Fe6D2C9857DD57aE78f3 |
| MegaETH | 0xA6A16C00B7E9DBE1D54acEd7d6FE264fc4732eaF |
| HyperEVM | 0x080b37C6F65cBC231f66016460782158090Fe0F7 |
| Monad | 0xaF9ADa6b6eC7993CE146f6c0bF98f7211CDfD3e5 |
All addresses are available programmatically:
import {
ADDRESSES,
ChainId,
getAddressesOrThrow,
} from "@nradko/metric-omm-sdk";
const ethAddresses = ADDRESSES[ChainId.ETHEREUM];
const arbAddresses = getAddressesOrThrow(42161);ABIs
ABIs are available as typed constants for direct use:
import {
MetricOmmPoolAbi,
MetricOmmSwapRouterAbi,
} from "@nradko/metric-omm-sdk/abis";Usage
The SDK is args-first. You build typed tuple args with a buildArgs... helper, then send the transaction yourself via walletClient.writeContract.
Liquidity
Build ModifyLiquidityArgs with the strategy you want (uniform addition, custom addition, percentage removal, or custom removal), then call pool modifyLiquidity with those args.
Available builders:
buildModifyLiquidityArgsForAddition(...)- custom per-bin addition amountsbuildModifyLiquidityArgsForUniformAddition(...)- uniform addition across a bin rangebuildModifyLiquidityArgsForRemoval(...)- remove custom per-bin share amounts/percentagesbuildModifyLiquidityArgsForPercentageRemoval(...)- remove a fixed percentage from selected bins/range
import {
buildModifyLiquidityArgsForUniformAddition,
getAddressesOrThrow,
} from "@nradko/metric-omm-sdk";
import { MetricOmmPoolAbi } from "@nradko/metric-omm-sdk/abis";
const addresses = getAddressesOrThrow(1);
const modifyLiquidityArgs = await buildModifyLiquidityArgsForUniformAddition({
publicClient,
stateViewAddress: addresses.stateView,
poolAddress,
amountInTokensPerBin: 1_000_000n,
amountIsInToken0: true,
currentPrice: 3000,
lowerBin: -5,
upperBin: 5,
salt: 0n,
});
const hash = await walletClient.writeContract({
address: poolAddress,
abi: MetricOmmPoolAbi,
functionName: "modifyLiquidity",
args: modifyLiquidityArgs,
account,
});Swaps
Build swap args first, then call the router function directly.
Available Args builders:
buildArgsForSwapExactInput(...)buildArgsForSwapExactOutput(...)
Additionally, these builders return args plus expected input/output amounts:
buildArgsAndExpectedAmountsForSwapExactInput(...)buildArgsAndExpectedAmountsForSwapExactOutput(...)
Quote-only helpers (no recipient/deadline required):
quoteExpectedAmountsForSwapExactInput(...)quoteExpectedAmountsForSwapExactOutput(...)
All swap build/quote helpers accept optional prices: { bidPriceX64, askPriceX64 }. If provided, the SDK uses them directly and skips reading from the pool price provider.
import {
buildArgsAndExpectedAmountsForSwapExactInput,
getAddressesOrThrow,
} from "@nradko/metric-omm-sdk";
import { MetricOmmSwapRouterAbi } from "@nradko/metric-omm-sdk/abis";
const addresses = getAddressesOrThrow(1);
const result = await buildArgsAndExpectedAmountsForSwapExactInput({
publicClient,
routerAddress: addresses.router,
pool: poolAddress,
recipient: account,
zeroForOne: true,
amountIn: 1_000_000_000_000_000_000n,
slippagePercent: 0.5,
deadline: BigInt(Math.floor(Date.now() / 1000) + 60 * 20),
});
const expectedInput = result.expectedInput;
const expectedOutput = result.expectedOutput;
const args = result.args;
const hash = await walletClient.writeContract({
address: addresses.router,
abi: MetricOmmSwapRouterAbi,
functionName: "swapExactInput",
args,
account,
});Development
Prerequisites
This SDK depends on @metric/core and @metric/periphery from private GitHub repositories.
Make sure your machine has SSH access to:
[email protected]:Metric-OMM/metric-core.git[email protected]:Metric-OMM/metric-periphery.git
Dependencies are pinned to exact commit SHAs in package.json.
Setup
npm installThis repo uses a native Git hook (no Husky) for pre-commit checks. If needed, you can set it manually:
npm run setup:hooksAfter install, postinstall runs automatically and compiles contracts and extracts ABIs.
To regenerate ABIs manually:
npm run sync:abisRunning Tests
npm testCommits are blocked unless bunx hardhat test succeeds.
Building
npm run buildAPI Reference
Address Helpers
ADDRESSES- Record of all deployed addresses by chain IDChainId- Enum of supported chain IDsgetAddresses(chainId)- Get addresses for a chain (returnsundefinedif unsupported)getAddressesOrThrow(chainId)- Get addresses or throw if unsupportedisChainSupported(chainId)- Check if a chain is supportedisChainDeployed(chainId)- Check if contracts are deployed on a chain
Pool Functions
preparePoolBinData(params)- Prepare legacy uniform bin arrays for pool creationprepareFactoryCreatePoolParams(params)- Build factory-ready pool params structencodeCreatePoolCalldata(params)- Encode create-pool calldata fromCreatePoolFactoryParamscreatePool(publicClient, walletClient, factoryAddress, params, account)- Simulate and send pool creation transactiongetPoolImmutables(client, poolAddress)- Get pool immutable parametersgetPoolState(client, poolAddress)- Get current pool stategetBinState(client, poolAddress, binIdx)- Get state of a specific bingetPositionBinShares(client, poolAddress, posKey)- Get position bin shares
Liquidity Functions
buildModifyLiquidityArgsForAddition(...)- BuildModifyLiquidityArgsfor custom additionbuildModifyLiquidityArgsForUniformAddition(...)- BuildModifyLiquidityArgsfor uniform additionbuildModifyLiquidityArgsForPercentageRemoval(...)- BuildModifyLiquidityArgsfor percentage removalbuildModifyLiquidityArgsForRemoval(...)- BuildModifyLiquidityArgsfor custom removalencodeModifyLiquidityCalldata(modifyLiquidityArgs)- EncodemodifyLiquiditycalldatagetPositionShares(client, stateViewAddress, poolAddress, owner, salt, lowerBin?, upperBin?)- Get position shares in a bin rangegetPositionSharesForBins(client, stateViewAddress, poolAddress, owner, salt, bins)- Get position shares for explicit binsNO_SLIPPAGE_LIMIT- Constant for no slippage limit
StateView Functions (Recommended for reads)
getSlot0(client, stateViewAddress, poolAddress)- Get slot0 data (bin index, position, drift, fees)getSlot1(client, stateViewAddress, poolAddress)- Get bin totalsgetBinStateExternal(client, stateViewAddress, poolAddress, binIdx)- Read a single bingetBinStatesExternal(client, stateViewAddress, poolAddress, binIndices)- Batch read binsgetBinStatesScaled(client, stateViewAddress, poolAddress, binIndices)- Batch read bins (scaled)getBinTotalShares(client, stateViewAddress, poolAddress, binIdx)- Get bin total sharesgetPositionBinSharesFromStateView(...)- Get position shares via state viewtoPositionBinKey(...)- Compute position bin keygetPositionBinSharesRange(...)- Get position shares for a range of binsgetFeeConfig(client, stateViewAddress, poolAddress)- Get fee configurationgetPriceProvider(client, stateViewAddress, poolAddress)- Get price provider addressgetLastTradeTimestamp(client, stateViewAddress, poolAddress)- Get last trade timestamp
Router Functions
buildArgsForSwapExactInput(params)- BuildSwapExactInputArgsusing on-chain quote and slippagebuildArgsAndExpectedAmountsForSwapExactInput(params)- Build exact-input args and return expected input/output amountsquoteExpectedAmountsForSwapExactInput(params)- Quote expected input/output for exact-input flow without building tx argsbuildArgsForSwapExactOutput(params)- BuildSwapExactOutputArgsusing on-chain quote and slippagebuildArgsAndExpectedAmountsForSwapExactOutput(params)- Build exact-output args and return expected input/output amountsquoteExpectedAmountsForSwapExactOutput(params)- Quote expected input/output for exact-output flow without building tx argsprepareSwapExactInputCalldata(argsOrParams)- Encode exact input swap calldataprepareSwapExactOutputCalldata(argsOrParams)- Encode exact output swap calldataprepareSwapExactInputNativeForTokensCalldata(params)- Encode native exact-input swap calldata
Utility Functions
priceToQ64(price)- Convert decimal price to Q64 fixed-point formatq64ToPrice(q64)- Convert Q64 fixed-point to decimal pricepackBinData(binData)- Pack a single bin data structpackBins5(bins)- Pack up to 5 bins into a single slotpackBinDataArray(bins)- Pack an array of bin dataunpackBinData(packed)- Unpack bin data from packed formatcreateBins(params)- Create bin data arraycreateUniformBins(count, weight, ...)- Create uniform bin distribution
