@meteora-ag/dlmm
Version:
<p align="center"> <img align="center" src="https://app.meteora.ag/icons/logo.svg" width="180" height="180" /> </p> <br>
365 lines (307 loc) • 18.1 kB
Markdown
# DLMM SDK
<p align="center">
<img align="center" src="https://app.meteora.ag/icons/logo.svg" width="180" height="180" />
</p>
<br>
## Getting started
NPM: https://www.npmjs.com/package/@meteora-ag/dlmm
SDK: https://github.com/MeteoraAg/dlmm-sdk
<!-- Docs: https://docs.mercurial.finance/mercurial-dynamic-yield-infra/ -->
Discord: https://discord.com/channels/841152225564950528/864859354335412224
## Install
1. Install deps
```
npm i -ag/dlmm @coral-xyz/anchor /web3.js
```
2. Initialize DLMM instance
```ts
import DLMM from '@meteora-ag/dlmm'
const USDC_USDT_POOL = new PublicKey('ARwi1S4DaiTG5DX7S4M4ZsrXqpMD1MrTmbu9ue2tpmEq') // You can get your desired pool address from the API https://dlmm-api.meteora.ag/pair/all
const dlmmPool = await DLMM.create(connection, USDC_USDT_POOL);
// If you need to create multiple, can consider using `createMultiple`
const dlmmPool = await DLMM.createMultiple(connection, [USDC_USDT_POOL, ...]);
```
3. To interact with the AmmImpl
- Get Active Bin
```ts
const activeBin = await dlmmPool.getActiveBin();
const activeBinPriceLamport = activeBin.price;
const activeBinPricePerToken = dlmmPool.fromPricePerLamport(
Number(activeBin.price),
);
```
- Create Balance Position
```ts
const TOTAL_RANGE_INTERVAL = 10; // 10 bins on each side of the active bin
const minBinId = activeBin.binId - TOTAL_RANGE_INTERVAL;
const maxBinId = activeBin.binId + TOTAL_RANGE_INTERVAL;
const totalXAmount = new BN(100 * 10 ** baseMint.decimals);
const totalYAmount = autoFillYByStrategy(
activeBin.binId,
dlmmPool.lbPair.binStep,
totalXAmount,
activeBin.xAmount,
activeBin.yAmount,
minBinId,
maxBinId,
StrategyType.Spot, // can be StrategyType.Spot, StrategyType.BidAsk, StrategyType.Curve
);
const newBalancePosition = new Keypair();
// Create Position
const createPositionTx =
await dlmmPool.initializePositionAndAddLiquidityByStrategy({
positionPubKey: newBalancePosition.publicKey,
user: user.publicKey,
totalXAmount,
totalYAmount,
strategy: {
maxBinId,
minBinId,
strategyType: StrategyType.Spot, // can be StrategyType.Spot, StrategyType.BidAsk, StrategyType.Curve
},
});
try {
const createBalancePositionTxHash = await sendAndConfirmTransaction(
connection,
createPositionTx,
[user, newBalancePosition],
);
} catch (error) {}
```
- Create Imbalance Position
```ts
const TOTAL_RANGE_INTERVAL = 10; // 10 bins on each side of the active bin
const minBinId = activeBin.binId - TOTAL_RANGE_INTERVAL;
const maxBinId = activeBin.binId + TOTAL_RANGE_INTERVAL;
const totalXAmount = new BN(100 * 10 ** baseMint.decimals);
const totalYAmount = new BN(0.5 * 10 ** 9); // SOL
const newImbalancePosition = new Keypair();
// Create Position
const createPositionTx =
await dlmmPool.initializePositionAndAddLiquidityByStrategy({
positionPubKey: newImbalancePosition.publicKey,
user: user.publicKey,
totalXAmount,
totalYAmount,
strategy: {
maxBinId,
minBinId,
strategyType: StrategyType.Spot, // can be StrategyType.Spot, StrategyType.BidAsk, StrategyType.Curve
},
});
try {
const createBalancePositionTxHash = await sendAndConfirmTransaction(
connection,
createPositionTx,
[user, newImbalancePosition],
);
} catch (error) {}
```
- Create One Side Position
```ts
const TOTAL_RANGE_INTERVAL = 10; // 10 bins on each side of the active bin
const minBinId = activeBin.binId;
const maxBinId = activeBin.binId + TOTAL_RANGE_INTERVAL * 2;
const totalXAmount = new BN(100 * 10 ** baseMint.decimals);
const totalYAmount = new BN(0);
const newOneSidePosition = new Keypair();
// Create Position
const createPositionTx =
await dlmmPool.initializePositionAndAddLiquidityByStrategy({
positionPubKey: newOneSidePosition.publicKey,
user: user.publicKey,
totalXAmount,
totalYAmount,
strategy: {
maxBinId,
minBinId,
strategyType: StrategyType.Spot, // can be StrategyType.Spot, StrategyType.BidAsk, StrategyType.Curve
},
});
try {
const createOneSidePositionTxHash = await sendAndConfirmTransaction(
connection,
createPositionTx,
[user, newOneSidePosition],
);
} catch (error) {}
```
- Get list of positions
```ts
const { userPositions } = await dlmmPool.getPositionsByUserAndLbPair(
user.publicKey,
);
const binData = userPositions[0].positionData.positionBinData;
```
- Add liquidity to existing position
```ts
const TOTAL_RANGE_INTERVAL = 10; // 10 bins on each side of the active bin
const minBinId = activeBin.binId - TOTAL_RANGE_INTERVAL;
const maxBinId = activeBin.binId + TOTAL_RANGE_INTERVAL;
const totalXAmount = new BN(100 * 10 ** baseMint.decimals);
const totalYAmount = autoFillYByStrategy(
activeBin.binId,
dlmmPool.lbPair.binStep,
totalXAmount,
activeBin.xAmount,
activeBin.yAmount,
minBinId,
maxBinId,
StrategyType.Spot, // can be StrategyType.Spot, StrategyType.BidAsk, StrategyType.Curve
);
// Add Liquidity to existing position
const addLiquidityTx = await dlmmPool.addLiquidityByStrategy({
positionPubKey: newBalancePosition.publicKey,
user: user.publicKey,
totalXAmount,
totalYAmount,
strategy: {
maxBinId,
minBinId,
strategyType: StrategyType.Spot, // can be StrategyType.Spot, StrategyType.BidAsk, StrategyType.Curve
},
});
try {
const addLiquidityTxHash = await sendAndConfirmTransaction(
connection,
addLiquidityTx,
[user],
);
} catch (error) {}
```
- Remove Liquidity
```ts
const userPosition = userPositions.find(({ publicKey }) =>
publicKey.equals(newBalancePosition.publicKey),
);
// Remove Liquidity
const binIdsToRemove = userPosition.positionData.positionBinData.map(
(bin) => bin.binId,
);
const removeLiquidityTx = await dlmmPool.removeLiquidity({
position: userPosition.publicKey,
user: user.publicKey,
fromBinId: binIdsToRemove[0],
toBinId: binIdsToRemove[binIdsToRemove.length - 1],
liquiditiesBpsToRemove: new Array(binIdsToRemove.length).fill(
new BN(100 * 100),
), // 100% (range from 0 to 100)
shouldClaimAndClose: true, // should claim swap fee and close position together
});
try {
for (let tx of Array.isArray(removeLiquidityTx)
? removeLiquidityTx
: [removeLiquidityTx]) {
const removeBalanceLiquidityTxHash = await sendAndConfirmTransaction(
connection,
tx,
[user],
{ skipPreflight: false, preflightCommitment: "singleGossip" },
);
}
} catch (error) {}
```
- Claim Fee
```ts
async function claimFee(dlmmPool: DLMM) {
const claimFeeTxs = await dlmmPool.claimAllSwapFee({
owner: user.publicKey,
positions: userPositions,
});
try {
for (const claimFeeTx of claimFeeTxs) {
const claimFeeTxHash = await sendAndConfirmTransaction(
connection,
claimFeeTx,
[user],
);
}
} catch (error) {}
}
```
- Close Position
```ts
const closePositionTx = await dlmmPool.closePosition({
owner: user.publicKey,
position: newBalancePosition.publicKey,
});
try {
const closePositionTxHash = await sendAndConfirmTransaction(
connection,
closePositionTx,
[user],
{ skipPreflight: false, preflightCommitment: "singleGossip" },
);
} catch (error) {}
```
- Swap
```ts
const swapAmount = new BN(0.1 * 10 ** 9);
// Swap quote
const swapYtoX = true;
const binArrays = await dlmmPool.getBinArrayForSwap(swapYtoX);
const swapQuote = await dlmmPool.swapQuote(
swapAmount,
swapYtoX,
new BN(1),
binArrays,
);
// Swap
const swapTx = await dlmmPool.swap({
inToken: dlmmPool.tokenX.publicKey,
binArraysPubkey: swapQuote.binArraysPubkey,
inAmount: swapAmount,
lbPair: dlmmPool.pubkey,
user: user.publicKey,
minOutAmount: swapQuote.minOutAmount,
outToken: dlmmPool.tokenY.publicKey,
});
try {
const swapTxHash = await sendAndConfirmTransaction(connection, swapTx, [
user,
]);
} catch (error) {}
```
## Static functions
| Function | Description | Return |
| ----------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------ |
| `create` | Given the DLMM address, create an instance to access the state and functions | `Promise<DLMM>` |
| `createMultiple` | Given a list of DLMM addresses, create instances to access the state and functions | `Promise<Array<DLMM>>` |
| `getAllPresetParameters` | Get all the preset params (use to create DLMM pool) | `Promise<PresetParams>` |
| `createPermissionLbPair` | Create DLMM Pool | `Promise<Transcation>` |
| `getClaimableLMReward` | Get Claimable LM reward for a position | `Promise<LMRewards>` |
| `getClaimableSwapFee` | Get Claimable Swap Fee for a position | `Promise<SwapFee>` |
| `getAllLbPairPositionsByUser` | Get user's all positions for all DLMM pools | `Promise<Map<string, PositionInfo>>` |
| `getPositionsByUserAndTokenAddress` | Get user's positions across all DLMM pools that contain a given token mint | `Promise<Map<string, PositionInfo>>` |
| `getLimitOrdersByUserAndTokenAddress` | Get user's limit orders across all DLMM pools that contain a given token mint, grouped by LB pair | `Promise<Map<string, LimitOrderInfo>>` |
## DLMM instance functions
| Function | Description | Return |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `refetchStates` | Update onchain state of DLMM instance. It's recommend to call this before interact with the program (Deposit/ Withdraw/ Swap) | `Promise<void>` |
| `getBinArrays` | Retrieves List of Bin Arrays | `Promise<BinArrayAccount[]>` |
| `getBinArrayForSwap` | Retrieves List of Bin Arrays for swap purpose | `Promise<BinArrayAccount[]>` |
| `getFeeInfo` | Retrieves LbPair's fee info including `base fee`, `protocol fee` & `max fee` | `FeeInfo` |
| `getDynamicFee` | Retrieves LbPair's dynamic fee | `Decimal` |
| `getBinsAroundActiveBin` | retrieves a specified number of bins to the left and right of the active bin and returns them along with the active bin ID. | `Promise<{ activeBin: number; bins: BinLiquidity[] }>` |
| `getBinsBetweenMinAndMaxPrice` | Retrieves a list of bins within a specified price | `Promise<{ activeBin: number; bins: BinLiquidity[] }>` |
| `getBinsBetweenLowerAndUpperBound` | retrieves a list of bins between a lower and upper bin ID and returns the active bin ID and the list of bins. | `Promise<{ activeBin: number; bins: BinLiquidity[] }>` |
| `toPricePerLamport` | Converts a real price of bin to lamport price | `string` |
| `fromPricePerLamport` | converts a price per lamport value to a real price of bin | `string` |
| `getActiveBin` | Retrieves the active bin ID and its corresponding price | `Promise<{ binId: number; price: string }>` |
| `getPriceOfBinByBinId` | Get the price of a bin based on its bin ID | `string` |
| `getBinIdFromPrice` | get bin ID based on a given price and a boolean flag indicating whether to round down or up. | `number` |
| `getPositionsByUserAndLbPair` | Retrieves positions by user and LB pair, including active bin and user positions. | `Promise<{ activeBin: { binId: any; price: string; }; userPositions: Array<Position>;}>` |
| `initializePositionAndAddLiquidityByStrategy` | Initializes a position and adds liquidity | `Promise<Transaction\|Transaction[]>` |
| `addLiquidityByStrategy` | Add liquidity to existing position | `Promise<Transaction\|Transaction[]>` |
| `removeLiquidity` | function is used to remove liquidity from a position, with the option to claim rewards and close the position. | `Promise<Transaction\|Transaction[]>` |
| `closePosition` | Closes a position | `Promise<Transaction\|Transaction[]>` |
| `swapQuote` | Quote for a swap | `SwapQuote` |
| `swap` | Swap token within the LbPair | `Promise<Transaction>` |
| `claimLMReward` | Claim rewards for a specific position owned by a specific owner | `Promise<Transaction>` |
| `claimAllLMRewards` | Claim all liquidity mining rewards for a given owner and their positions. | `Promise<Transaction[]>` |
| `claimSwapFee` | Claim swap fees for a specific position owned by a specific owner | `Promise<Transaction>` |
| `claimAllSwapFee` | Claim swap fees for multiple positions owned by a specific owner | `Promise<Transaction>` |
| `claimAllRewards` | Claim swap fees and LM rewards for multiple positions owned by a specific owner | `Promise<Transaction[]>` |
| `syncWithMarketPrice` | Sync the pool current active bin to match nearest market price bin | `Promise<Transaction>` |
| `getPairPubkeyIfExists` | Get existing pool address given parameter, if not return null | `Promise<PublicKey \| null>` |
| `getMaxPriceInBinArrays` | Get max price of the last bin that has liquidity given bin arrays | `Promise<string \| null>` |