유동성 추가하기

이 가이드는 Saros DLMM 유동성 풀에 프론트엔드 통합을 통해 유동성을 주입하는 방법을 설명합니다. 두 가지 주요 플로우는 다음과 같습니다:

  • 기존 포지션이 없을 때 새 포지션 생성

  • 기존 포지션에 유동성 추가

두 플로우에서 공통되는 핵심 단계:

  • 예치할 토큰 수량 계산

  • 관련 온체인 명령어 호출

새 포지션 생성(Creating a New Position)

새로운 유동성 포지션을 생성하려면 다음 단계를 수행해야 합니다:

  1. 포지션의 빈 범위(bin range) 결정, 활성 빈(Active Bin)을 기준으로 상대적 빈 ID(Relative Bin ID)를 지정합니다:

    relative_bin_id_left: 활성 빈 기준 가장 왼쪽 빈의 상대 ID

    relative_bin_id_right: 활성 빈 기준 가장 오른쪽 빈의 상대 ID

  2. Create_position 명령어 호출, 위 파라미터를 사용해 포지션을 생성합니다.

  3. 포지션 생성 후, increase_position 명령어를 사용하여 유동성을 추가합니다.

예시 구현(Example Implementation)

import { createMint } from "@solana/spl-token";
import { PublicKey, SystemProgram } from "@solana/web3.js";
import { BN } from "@project-serum/anchor";
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";

// Create a new position
const relativeBinIdLeft = -5;  // 5 bins to the left of active bin
const relativeBinIdRight = 5;  // 5 bins to the right of active bin

// Create position mint first
const positionMint = await createMint(
  connection,
  wallet.payer,
  wallet.publicKey,
  null,
  0,
  undefined,
  undefined,
  TOKEN_2022_PROGRAM_ID
);

// Derive PDAs
const [positionPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("position"), positionMint.toBuffer()],
  program.programId
);

const [positionTokenAccount] = PublicKey.findProgramAddressSync(
  [
    wallet.publicKey.toBuffer(),
    TOKEN_2022_PROGRAM_ID.toBuffer(),
    positionMint.toBuffer(),
  ],
  ASSOCIATED_TOKEN_PROGRAM_ID
);

await program.methods
  .createPosition(new BN(relativeBinIdLeft), new BN(relativeBinIdRight))
  .accounts({
    pair: pairPda,
    position: positionPda,
    positionMint: positionMint,
    positionTokenAccount: positionTokenAccount,
    user: wallet.publicKey,
    systemProgram: SystemProgram.programId,
    tokenProgram: TOKEN_2022_PROGRAM_ID,
    associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
  })
  .signers([positionMint])
  .rpc();

// Add liquidity to the position
const amountX = new BN(1000000); // Amount of token X
const amountY = new BN(1000000); // Amount of token Y

// Define liquidity distribution across bins
const liquidityDistribution = [
  { relativeBinId: -5, distributionX: 1000, distributionY: 0 },
  { relativeBinId: -4, distributionX: 2000, distributionY: 0 },
  { relativeBinId: -3, distributionX: 3000, distributionY: 0 },
  { relativeBinId: -2, distributionX: 2000, distributionY: 0 },
  { relativeBinId: -1, distributionX: 1000, distributionY: 0 },
  { relativeBinId: 0, distributionX: 500, distributionY: 500 },
  { relativeBinId: 1, distributionX: 0, distributionY: 1000 },
  { relativeBinId: 2, distributionX: 0, distributionY: 2000 },
  { relativeBinId: 3, distributionX: 0, distributionY: 3000 },
  { relativeBinId: 4, distributionX: 0, distributionY: 2000 },
  { relativeBinId: 5, distributionX: 0, distributionY: 1000 },
];

// Derive bin array PDAs
const [binArrayLowerPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("bin_array"), pairPda.toBuffer(), Buffer.from([0])],
  program.programId
);

const [binArrayUpperPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("bin_array"), pairPda.toBuffer(), Buffer.from([1])],
  program.programId
);

await program.methods
  .increasePosition(amountX, amountY, liquidityDistribution)
  .accounts({
    pair: pairPda,
    position: positionPda,
    binArrayLower: binArrayLowerPda,
    binArrayUpper: binArrayUpperPda,
    tokenMintX: tokenMintX,
    tokenMintY: tokenMintY,
    tokenVaultX: tokenVaultXPda,
    tokenVaultY: tokenVaultYPda,
    userVaultX: userVaultXPda,
    userVaultY: userVaultYPda,
    positionTokenAccount: positionTokenAccount,
    tokenProgramX: TOKEN_2022_PROGRAM_ID,
    tokenProgramY: TOKEN_2022_PROGRAM_ID,
    positionTokenProgram: TOKEN_2022_PROGRAM_ID,
    systemProgram: SystemProgram.programId,
    memoProgram: MEMO_PROGRAM_ID,
  })
  .remainingAccounts([
    { pubkey: pairPda, isWritable: false, isSigner: false },
    { pubkey: binArrayLowerPda, isWritable: false, isSigner: false },
    { pubkey: binArrayUpperPda, isWritable: false, isSigner: false },
  ])
  .rpc();

Increasing an Existing Position

기존 포지션에 더 많은 유동성을 추가하려면 다음 단계를 수행합니다:

  1. 추가할 토큰 X와 토큰 Y의 수량을 계산합니다.

  2. 각 빈(Bin)에 유동성을 어떻게 분배할지 설정합니다.

  3. increase_position 명령어 호출:

    • amountX: 추가할 토큰 X의 양

    • amountY: 추가할 토큰 Y의 양

    • liquidityDistribution: 각 빈에 유동성을 어떻게 분배할지 지정하는 BinLiquidityDistribution 객체 배열

유동성 분배 포맷(Liquidity Distribution Format)

liquidityDistribution 파라미터는 다음 구조를 가진 객체 배열입니다:

참고 사항(Notes):

  • 분배 값은 기준점(basis points) 단위로 입력되며, 범위는 0–10000입니다.

  • 음수(relativeBinId < 0)인 빈에는 토큰 X만 분배할 수 있습니다.

  • 양수(relativeBinId > 0)인 빈에는 토큰 Y만 분배할 수 있습니다.

  • relativeBinId = 0인 활성 빈에는 두 토큰 모두 분배할 수 있습니다.

  • 모든 분배 값의 합계는 반드시 10000(= 100%)이어야 합니다.

Last updated