@raydium-io/raydium-sdk-v2
Version:
An SDK for building applications on top of Raydium.
208 lines (195 loc) • 6.79 kB
text/typescript
import { Connection, PublicKey } from "@solana/web3.js";
import BN from "bn.js";
import Decimal from "decimal.js";
import { AmmV4Keys, AmmV5Keys } from "../../api/type";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import {
findProgramAddress,
parseSimulateLogToJson,
parseSimulateValue,
simulateMultipleInstruction,
} from "@/common/txTool/txUtils";
import { toApiV3Token } from "../../raydium/token/utils";
import { getSerumAssociatedAuthority } from "./serum";
import { StableLayout } from "./stable";
import { AmmRpcData, ComputeAmountOutParam, LiquidityPoolKeys } from "./type";
import { liquidityStateV4Layout } from "./layout";
import { splAccountLayout } from "../account";
import { SPL_MINT_LAYOUT } from "../token";
type AssociatedName =
| "amm_associated_seed"
| "lp_mint_associated_seed"
| "coin_vault_associated_seed"
| "pc_vault_associated_seed"
| "lp_mint_associated_seed"
| "temp_lp_token_associated_seed"
| "open_order_associated_seed"
| "target_associated_seed"
| "withdraw_associated_seed";
interface GetAssociatedParam {
name: AssociatedName;
programId: PublicKey;
marketId: PublicKey;
}
export function getAssociatedConfigId({ programId }: { programId: PublicKey }): PublicKey {
const { publicKey } = findProgramAddress([Buffer.from("amm_config_account_seed", "utf-8")], programId);
return publicKey;
}
export function getLiquidityAssociatedId({ name, programId, marketId }: GetAssociatedParam): PublicKey {
const { publicKey } = findProgramAddress(
[programId.toBuffer(), marketId.toBuffer(), Buffer.from(name, "utf-8")],
programId,
);
return publicKey;
}
export function getAssociatedOpenOrders({ programId, marketId }: { programId: PublicKey; marketId: PublicKey }) {
const { publicKey } = findProgramAddress(
[programId.toBuffer(), marketId.toBuffer(), Buffer.from("open_order_associated_seed", "utf-8")],
programId,
);
return publicKey;
}
export function getLiquidityAssociatedAuthority({ programId }: { programId: PublicKey }): {
publicKey: PublicKey;
nonce: number;
} {
return findProgramAddress([Buffer.from([97, 109, 109, 32, 97, 117, 116, 104, 111, 114, 105, 116, 121])], programId);
}
export function getAssociatedPoolKeys({
version,
marketVersion,
marketId,
baseMint,
quoteMint,
baseDecimals,
quoteDecimals,
programId,
marketProgramId,
}: {
version: 4 | 5;
marketVersion: 3;
marketId: PublicKey;
baseMint: PublicKey;
quoteMint: PublicKey;
baseDecimals: number;
quoteDecimals: number;
programId: PublicKey;
marketProgramId: PublicKey;
}): LiquidityPoolKeys {
const id = getLiquidityAssociatedId({ name: "amm_associated_seed", programId, marketId });
const lpMint = getLiquidityAssociatedId({ name: "lp_mint_associated_seed", programId, marketId });
const { publicKey: authority, nonce } = getLiquidityAssociatedAuthority({ programId });
const baseVault = getLiquidityAssociatedId({ name: "coin_vault_associated_seed", programId, marketId });
const quoteVault = getLiquidityAssociatedId({ name: "pc_vault_associated_seed", programId, marketId });
const lpVault = getLiquidityAssociatedId({ name: "temp_lp_token_associated_seed", programId, marketId });
const openOrders = getAssociatedOpenOrders({ programId, marketId });
const targetOrders = getLiquidityAssociatedId({ name: "target_associated_seed", programId, marketId });
const withdrawQueue = getLiquidityAssociatedId({ name: "withdraw_associated_seed", programId, marketId });
const { publicKey: marketAuthority } = getSerumAssociatedAuthority({
programId: marketProgramId,
marketId,
});
return {
// base
id,
baseMint,
quoteMint,
lpMint,
baseDecimals,
quoteDecimals,
lpDecimals: baseDecimals,
// version
version,
programId,
// keys
authority,
nonce,
baseVault,
quoteVault,
lpVault,
openOrders,
targetOrders,
withdrawQueue,
// market version
marketVersion,
marketProgramId,
// market keys
marketId,
marketAuthority,
lookupTableAccount: PublicKey.default,
configId: getAssociatedConfigId({ programId }),
};
}
const mockRewardData = {
volume: 0,
volumeQuote: 0,
volumeFee: 0,
apr: 0,
feeApr: 0,
priceMin: 0,
priceMax: 0,
rewardApr: [],
};
export const toAmmComputePoolInfo = (
poolData: Record<string, AmmRpcData>,
): Record<string, ComputeAmountOutParam["poolInfo"]> => {
const data: Record<string, ComputeAmountOutParam["poolInfo"]> = {};
const tokenProgramStr = TOKEN_PROGRAM_ID.toBase58();
Object.keys(poolData).map((poolId) => {
const poolInfo = poolData[poolId];
const [mintA, mintB] = [poolInfo.baseMint.toBase58(), poolInfo.quoteMint.toBase58()];
data[poolId] = {
id: poolId,
version: 4,
status: poolInfo.status.toNumber(),
programId: poolInfo.programId.toBase58(), // needed
mintA: toApiV3Token({
address: mintA, // needed
programId: tokenProgramStr,
decimals: poolInfo.baseDecimal.toNumber(),
}),
mintB: toApiV3Token({
address: mintB, // needed
programId: tokenProgramStr,
decimals: poolInfo.quoteDecimal.toNumber(),
}),
rewardDefaultInfos: [],
rewardDefaultPoolInfos: "Ecosystem",
price: poolInfo.poolPrice.toNumber(),
mintAmountA: new Decimal(poolInfo.mintAAmount.toString()).div(10 ** poolInfo.baseDecimal.toNumber()).toNumber(),
mintAmountB: new Decimal(poolInfo.mintBAmount.toString()).div(10 ** poolInfo.quoteDecimal.toNumber()).toNumber(),
baseReserve: poolInfo.baseReserve, // needed
quoteReserve: poolInfo.quoteReserve, // needed
feeRate: new Decimal(poolInfo.tradeFeeNumerator.toString())
.div(poolInfo.tradeFeeDenominator.toString())
.toNumber(),
openTime: poolInfo.poolOpenTime.toString(),
tvl: 0,
day: mockRewardData,
week: mockRewardData,
month: mockRewardData,
pooltype: [],
farmUpcomingCount: 0,
farmOngoingCount: 0,
farmFinishedCount: 0,
type: "Standard",
marketId: poolInfo.marketId.toBase58(),
configId: getAssociatedConfigId({ programId: poolInfo.programId }).toBase58(),
lpPrice: 0,
lpAmount: new Decimal(poolInfo.lpReserve.toString())
.div(10 ** Math.min(poolInfo.baseDecimal.toNumber(), poolInfo.quoteDecimal.toNumber()))
.toNumber(),
lpMint: toApiV3Token({
address: poolInfo.lpMint.toBase58(),
programId: tokenProgramStr,
decimals: Math.min(poolInfo.baseDecimal.toNumber(), poolInfo.quoteDecimal.toNumber()),
}),
burnPercent: 0,
feeOn: "Both",
hasDynamicFee: false,
tips: [],
launchMigratePool: false,
};
});
return data;
};