Skip to content

Commit

Permalink
Merge pull request sendaifun#3 from quangkeu95/feat/meteora
Browse files Browse the repository at this point in the history
feat: Create Meteora pools
  • Loading branch information
quangkeu95 authored Jan 13, 2025
2 parents fcbb2e1 + 1e00dab commit 7d6327a
Show file tree
Hide file tree
Showing 14 changed files with 5,111 additions and 5,188 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
"@metaplex-foundation/umi": "^0.9.2",
"@metaplex-foundation/umi-bundle-defaults": "^0.9.2",
"@metaplex-foundation/umi-web3js-adapters": "^0.9.2",
"@mercurial-finance/dynamic-amm-sdk": "^1.1.19",
"@meteora-ag/alpha-vault": "^1.1.7",
"@meteora-ag/dlmm": "^1.3.0",
"@onsol/tldparser": "^0.6.7",
"@orca-so/common-sdk": "0.6.4",
"@orca-so/whirlpools-sdk": "^0.13.12",
Expand Down Expand Up @@ -78,4 +81,4 @@
"tsx": "^4.19.2",
"typescript": "^5.7.2"
}
}
}
9,630 changes: 4,443 additions & 5,187 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions src/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ import {
fetchPythPriceFeedID,
flashOpenTrade,
flashCloseTrade,
createMeteoraDynamicAMMPool,
createMeteoraDlmmPool,
createCollection,
createSingle,
multisig_transfer_from_treasury,
Expand Down Expand Up @@ -338,6 +340,61 @@ export class SolanaAgentKit {
);
}

async meteoraCreateDynamicPool(
tokenAMint: PublicKey,
tokenBMint: PublicKey,
tokenAAmount: BN,
tokenBAmount: BN,
tradeFeeNumerator: number,
activationPoint: BN | null,
hasAlphaVault: boolean,
activationType: number,
computeUnitMicroLamports: number = 100000,
): Promise<string> {
return createMeteoraDynamicAMMPool(
this,
tokenAMint,
tokenBMint,
tokenAAmount,
tokenBAmount,
{
tradeFeeNumerator,
activationPoint,
hasAlphaVault,
activationType,
padding: new Array(90).fill(0),
},
computeUnitMicroLamports,
);
}

async meteoraCreateDlmmPool(
tokenAMint: PublicKey,
tokenBMint: PublicKey,
binStep: number,
initialPrice: number,
priceRoundingUp: boolean,
feeBps: number,
activationType: number,
hasAlphaVault: boolean,
activationPoint: BN | undefined,
computeUnitMicroLamports: number = 100000,
): Promise<string> {
return createMeteoraDlmmPool(
this,
binStep,
tokenAMint,
tokenBMint,
initialPrice,
priceRoundingUp,
feeBps,
activationType,
hasAlphaVault,
activationPoint,
computeUnitMicroLamports,
);
}

async orcaClosePosition(positionMintAddress: PublicKey) {
return orcaClosePosition(this, positionMintAddress);
}
Expand Down
9 changes: 9 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,18 @@ export const DEFAULT_OPTIONS = {
LEVERAGE_BPS: 50000, // 10000 = x1, 50000 = x5, 100000 = x10, 1000000 = x100
} as const;

export const METEORA_DYNAMIC_FEE_DENOMINATOR = 100000;

/**
* Jupiter API URL
*/
export const JUP_API = "https://quote-api.jup.ag/v6";
export const JUP_REFERRAL_ADDRESS =
"REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3";

export const METEORA_DYNAMIC_AMM_PROGRAM_ID = new PublicKey(
"Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB",
);
export const METEORA_DLMM_PROGRAM_ID = new PublicKey(
"LbVRzDTvBDEcrthxfZ4RL6yiq3uZw8bS6MwtdY6UhFQ",
);
5 changes: 5 additions & 0 deletions src/langchain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export * from "./tiplink";
export * from "./sns";
export * from "./lightprotocol";
export * from "./squads";
export * from "./meteora";

import { SolanaAgentKit } from "../agent";
import {
Expand Down Expand Up @@ -91,6 +92,8 @@ import {
SolanaApproveProposal2by2Multisig,
SolanaExecuteProposal2by2Multisig,
SolanaRejectProposal2by2Multisig,
SolanaMeteoraCreateDynamicPool,
SolanaMeteoraCreateDlmmPool,
} from "./index";

export function createSolanaTools(solanaKit: SolanaAgentKit) {
Expand Down Expand Up @@ -125,6 +128,8 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
new SolanaBatchOrderTool(solanaKit),
new SolanaCancelAllOrdersTool(solanaKit),
new SolanaWithdrawAllTool(solanaKit),
new SolanaMeteoraCreateDynamicPool(solanaKit),
new SolanaMeteoraCreateDlmmPool(solanaKit),
new SolanaClosePosition(solanaKit),
new SolanaOrcaCreateCLMM(solanaKit),
new SolanaOrcaCreateSingleSideLiquidityPool(solanaKit),
Expand Down
2 changes: 2 additions & 0 deletions src/langchain/meteora/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./meteora_dlmm_pool";
export * from "./meteora_dynamic_pool";
83 changes: 83 additions & 0 deletions src/langchain/meteora/meteora_dlmm_pool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { PublicKey } from "@solana/web3.js";
import { Tool } from "langchain/tools";
import { SolanaAgentKit } from "../../agent";
import { BN } from "bn.js";

export class SolanaMeteoraCreateDlmmPool extends Tool {
name = "meteora_create_dlmm_pool";
description = `Create a Meteora DLMM Pool. This function doesn't add liquidity.
Inputs (JSON string):
- tokenAMint: string, token A mint (required).
- tokenBMint: string, token B mint (required).
- binStep: number, pool bin step, e.g., 20 (required).
- initialPrice: number, pool initial price, e.g., 0.25 (required).
- feeBps: number, trade fee in percentage, e.g. 20 for 0.2% (required).
- priceRoundingUp: boolean, whether the initial price should be rounded up or not, default is true (optional).
- activationType: number, pool start trading time indicator. 0 is slot and 1 is timestamp, default is 1 for timestamp (optional).
- activationPoint: number, pool start trading slot / timestamp, default is null means pool can start trading immediately (optional).
- hasAlphaVault: boolean, whether the pool supports alpha vault, default is false (optional).
- computeUnitMicroLamports: number, the priority fee in micro-lamports unit, default is 100000 (optional).
`;

constructor(private solanaKit: SolanaAgentKit) {
super();
}

async _call(input: string): Promise<string> {
try {
interface CreateMeteoraDlmmPoolInput {
tokenAMint: string;
tokenBMint: string;
binStep: number;
initialPrice: number;
feeBps: number;
priceRoundingUp?: boolean;
activationType?: number;
activationPoint?: number;
hasAlphaVault?: boolean;
computeUnitMicroLamports?: number;
}
const inputFormat: CreateMeteoraDlmmPoolInput = JSON.parse(input);

const tokenAMint = new PublicKey(inputFormat.tokenAMint);
const tokenBMint = new PublicKey(inputFormat.tokenBMint);
const binStep = inputFormat.binStep;
const initialPrice = inputFormat.initialPrice;
const feeBps = inputFormat.feeBps;
const priceRoundingUp = inputFormat.priceRoundingUp ?? true;
const activationType = inputFormat.activationType ?? 1;
const activationPoint = inputFormat.activationPoint
? new BN(inputFormat.activationPoint)
: undefined;
const hasAlphaVault = inputFormat.hasAlphaVault ?? false;
const computeUnitMicroLamports =
inputFormat.computeUnitMicroLamports ?? 100000;

const txId = await this.solanaKit.meteoraCreateDlmmPool(
tokenAMint,
tokenBMint,
binStep,
initialPrice,
priceRoundingUp,
feeBps,
activationType,
hasAlphaVault,
activationPoint,
computeUnitMicroLamports,
);

return JSON.stringify({
status: "success",
message: "Meteora DLMM pool created successfully.",
transaction: txId,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
82 changes: 82 additions & 0 deletions src/langchain/meteora/meteora_dynamic_pool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { PublicKey } from "@solana/web3.js";
import { Tool } from "langchain/tools";
import { SolanaAgentKit } from "../../agent";
import { BN } from "bn.js";

export class SolanaMeteoraCreateDynamicPool extends Tool {
name = "meteora_create_dynamic_pool";
description = `Create a Meteora Dynamic Pool. This function adds liquidity with a constant-product formula.
Inputs (JSON string):
- tokenAMint: string, token A mint (required).
- tokenBMint: string, token B mint (required).
- tokenAAmount: number, token A amount including decimals, e.g., 1000000000 (required).
- tokenBAmount: number, token B amount including decimals, e.g., 1000000000 (required).
- tradeFeeNumerator: number, trade fee numerator, e.g., 2500 for 2.5% (required).
- activationType: number, pool start trading time indicator, 0 is slot and 1 is timestamp, default is 1 for timestamp (optional).
- activationPoint: number, pool start trading slot / timestamp, default is null means pool can start trading immediately (optional).
- hasAlphaVault: boolean, whether the pool supports alpha vault, default is false (optional).
- computeUnitMicroLamports: number, the priority fee in micro-lamports unit, default is 100000 (optional).
`;

constructor(private solanaKit: SolanaAgentKit) {
super();
}

async _call(input: string): Promise<string> {
try {
interface CreateMeteoraDynamicAmmPoolInput {
tokenAMint: string;
tokenBMint: string;
tokenAAmount: number;
tokenBAmount: number;
tradeFeeNumerator: number;
activationType?: number;
activationPoint?: number;
hasAlphaVault?: boolean;
computeUnitMicroLamports?: number;
}
const inputFormat: CreateMeteoraDynamicAmmPoolInput = JSON.parse(input);

const tokenAMint = new PublicKey(inputFormat.tokenAMint);
const tokenBMint = new PublicKey(inputFormat.tokenBMint);
const tokenAAmount = new BN(inputFormat.tokenAAmount.toString());
const tokenBAmount = new BN(inputFormat.tokenBAmount.toString());

const tradeFeeNumerator = new BN(
inputFormat.tradeFeeNumerator.toString(),
).toNumber();
const activationType = inputFormat.activationType ?? 1;
const activationPoint = inputFormat.activationPoint
? new BN(inputFormat.activationPoint)
: null;
const hasAlphaVault = inputFormat.hasAlphaVault ?? false;
const computeUnitMicroLamports =
inputFormat.computeUnitMicroLamports ?? 100000;

const txId = await this.solanaKit.meteoraCreateDynamicPool(
tokenAMint,
tokenBMint,
tokenAAmount,
tokenBAmount,
tradeFeeNumerator,
activationPoint,
hasAlphaVault,
activationType,
computeUnitMicroLamports,
);

return JSON.stringify({
status: "success",
message: "Meteora Dynamic pool created successfully.",
transaction: txId,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
Loading

0 comments on commit 7d6327a

Please sign in to comment.