From ddd41974aaab4c23efd9da409f6a9354984a6bb9 Mon Sep 17 00:00:00 2001
From: McSam
Date: Thu, 11 Jan 2024 21:30:04 +0800
Subject: [PATCH] add readme
---
ts-client/README.md | 187 +++++++++++++++++++++++++++++++++++++++
ts-client/package.json | 3 +-
ts-client/src/example.ts | 39 ++++++--
3 files changed, 221 insertions(+), 8 deletions(-)
diff --git a/ts-client/README.md b/ts-client/README.md
index 44208f76..678c4699 100644
--- a/ts-client/README.md
+++ b/ts-client/README.md
@@ -5,6 +5,189 @@
+## Getting started
+
+NPM: https://www.npmjs.com/package/@meteora-ag/dlmm-sdk-public
+
+SDK: https://github.com/MeteoraAg/dlmm-sdk
+
+
+
+Discord: https://discord.com/channels/841152225564950528/864859354335412224
+
+## Install
+
+1. Install deps
+
+```
+npm i @meteora-ag/dlmm-sdk-public @coral-xyz/anchor @solana/web3.js
+```
+
+2. Initialize DLMM instance
+
+```ts
+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, {
+ cluster: "devnet",
+});
+
+// If you need to create multiple, can consider using `createMultiple`
+const dlmmPool = await DLMM.create(connection, [USDC_USDT_POOL, ...], {
+ cluster: "devnet",
+});
+
+```
+
+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 Position
+
+```ts
+const TOTAL_RANGE_INTERVAL = 10; // 10 bins on each side of the active bin
+const bins = [activeBin.binId]; // Make sure bins is less than 70, as currently only support up to 70 bins for 1 position
+for (
+ let i = activeBin.binId;
+ i < activeBin.binId + TOTAL_RANGE_INTERVAL / 2;
+ i++
+) {
+ const rightNextBinId = i + 1;
+ const leftPrevBinId = activeBin.binId - (rightNextBinId - activeBin.binId);
+ bins.push(rightNextBinId);
+ bins.unshift(leftPrevBinId);
+}
+
+const activeBinPricePerToken = dlmmPool.fromPricePerLamport(
+ Number(activeBin.price)
+);
+const totalXAmount = new BN(100);
+const totalYAmount = totalXAmount.mul(new BN(Number(activeBinPricePerToken)));
+
+// Get spot distribution (You can calculate with other strategy `calculateSpotDistribution`, `calculateNormalDistribution`)
+const spotXYAmountDistribution = calculateSpotDistribution(
+ activeBin.binId,
+ bins
+);
+const newPosition = new Keypair();
+const createPositionTx =
+ await dlmmPool.initializePositionAndAddLiquidityByWeight({
+ positionPubKey: newPosition.publicKey,
+ lbPairPubKey: dlmmPool.pubkey,
+ user: user.publicKey,
+ totalXAmount,
+ totalYAmount,
+ xYAmountDistribution: spotXYAmountDistribution,
+ });
+
+try {
+ for (let tx of Array.isArray(createPositionTx)
+ ? createPositionTx
+ : [createPositionTx]) {
+ const createPositionTxHash = await sendAndConfirmTransaction(
+ connection,
+ tx,
+ [user, newPosition]
+ );
+ }
+} 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 addLiquidityTx = await dlmmPool.addLiquidityByWeight({
+ positionPubKey: userPositions[0].publicKey,
+ lbPairPubKey: dlmmPool.pubkey,
+ user: user.publicKey,
+ totalXAmount,
+ totalYAmount,
+ xYAmountDistribution: spotXYAmountDistribution,
+});
+
+try {
+ for (let tx of Array.isArray(addLiquidityTx)
+ ? addLiquidityTx
+ : [addLiquidityTx]) {
+ const addLiquidityTxHash = await sendAndConfirmTransaction(connection, tx, [
+ user,
+ newPosition,
+ ]);
+ }
+} catch (error) {}
+```
+
+- Remove Liquidity
+
+```ts
+const binIdsToRemove = userPositions[0].positionData.positionBinData.map(
+ (bin) => bin.binId
+);
+const removeLiquidityTx = await dlmmPool.removeLiquidity({
+ position: userPositions[0].publicKey,
+ user: user.publicKey,
+ binIds: binIdsToRemove,
+ 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 removeLiquidityTxHash = await sendAndConfirmTransaction(
+ connection,
+ tx,
+ [user, newPosition]
+ );
+ }
+} catch (error) {}
+```
+
+- Swap
+
+```ts
+const swapAmount = new BN(100);
+// Swap quote
+const swapQuote = await dlmmPool.swapQuote(swapAmount, true, new BN(10));
+
+// 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 |
@@ -41,3 +224,7 @@
| `claimSwapFee` | Claim swap fees for a specific position owned by a specific owner | `Promise` |
| `claimAllSwapFee` | Claim swap fees for multiple positions owned by a specific owner | `Promise` |
| `claimAllRewards` | Claim swap fees and LM rewards for multiple positions owned by a specific owner | `Promise` |
+
+```
+
+```
diff --git a/ts-client/package.json b/ts-client/package.json
index 0fb6f05b..3ca2d9cf 100644
--- a/ts-client/package.json
+++ b/ts-client/package.json
@@ -6,7 +6,8 @@
"scripts": {
"build": "tsup",
"start": "npm run build -- --watch",
- "test": "jest src/test/sdk.test.ts"
+ "test": "jest src/test/sdk.test.ts",
+ "example": "dotenv -e .env npx ts-node src/example.ts"
},
"devDependencies": {
"@babel/preset-env": "^7.22.5",
diff --git a/ts-client/src/example.ts b/ts-client/src/example.ts
index dc957e1b..54ecdd32 100644
--- a/ts-client/src/example.ts
+++ b/ts-client/src/example.ts
@@ -4,12 +4,13 @@ import {
PublicKey,
sendAndConfirmTransaction,
} from "@solana/web3.js";
+import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
import { DLMM } from "./dlmm";
import { calculateSpotDistribution } from "./dlmm/helpers";
import BN from "bn.js";
const user = Keypair.fromSecretKey(
- new Uint8Array(JSON.parse(process.env.USER_PRIVATE_KEY))
+ new Uint8Array(bs58.decode(process.env.USER_PRIVATE_KEY))
);
const RPC = process.env.RPC || "https://api.devnet.solana.com";
const connection = new Connection(RPC, "finalized");
@@ -44,7 +45,7 @@ async function main() {
Number(activeBin.price)
);
const totalXAmount = new BN(100);
- const totalYAmount = totalXAmount.mul(new BN(activeBinPricePerToken));
+ const totalYAmount = totalXAmount.mul(new BN(Number(activeBinPricePerToken)));
// Get spot distribution
const spotXYAmountDistribution = calculateSpotDistribution(
@@ -52,7 +53,7 @@ async function main() {
bins
);
- // Add Liquidity
+ // Create Position
const newPosition = new Keypair();
const createPositionTx =
await dlmmPool.initializePositionAndAddLiquidityByWeight({
@@ -71,8 +72,7 @@ async function main() {
const createPositionTxHash = await sendAndConfirmTransaction(
connection,
tx,
- [user, newPosition],
- { skipPreflight: false, preflightCommitment: "singleGossip" }
+ [user, newPosition]
);
console.log("🚀 ~ createPositionTxHash:", createPositionTxHash);
}
@@ -82,10 +82,35 @@ async function main() {
// Get position state
const { userPositions } = await dlmmPool.getPositionsByUserAndLbPair(
- newPosition.publicKey
+ user.publicKey
);
console.log("🚀 ~ userPositions:", userPositions);
+ // Add Liquidity to existing position
+ const addLiquidityTx = await dlmmPool.addLiquidityByWeight({
+ positionPubKey: userPositions[0].publicKey,
+ lbPairPubKey: dlmmPool.pubkey,
+ user: user.publicKey,
+ totalXAmount,
+ totalYAmount,
+ xYAmountDistribution: spotXYAmountDistribution,
+ });
+
+ try {
+ for (let tx of Array.isArray(addLiquidityTx)
+ ? addLiquidityTx
+ : [addLiquidityTx]) {
+ const addLiquidityTxHash = await sendAndConfirmTransaction(
+ connection,
+ tx,
+ [user, newPosition]
+ );
+ console.log("🚀 ~ addLiquidityTxHash:", addLiquidityTxHash);
+ }
+ } catch (error) {
+ console.log("🚀 ~ error:", JSON.parse(JSON.stringify(error)));
+ }
+
// Remove Liquidity
const binIdsToRemove = userPositions[0].positionData.positionBinData.map(
(bin) => bin.binId
@@ -110,7 +135,7 @@ async function main() {
[user, newPosition],
{ skipPreflight: false, preflightCommitment: "singleGossip" }
);
- console.log("🚀 ~ createPositionTxHash:", removeLiquidityTxHash);
+ console.log("🚀 ~ removeLiquidityTxHash:", removeLiquidityTxHash);
}
} catch (error) {
console.log("🚀 ~ error:", JSON.parse(JSON.stringify(error)));