forked from raydium-io/raydium-sdk-V1-demo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { ApiClmmPoolsItem, MathUtil, PoolInfoLayout } from "@raydium-io/raydium-sdk" | ||
import { ParsedAccountData, PublicKey } from "@solana/web3.js" | ||
import Decimal from "decimal.js" | ||
import { ENDPOINT, RAYDIUM_MAINNET_API, connection } from "../config" | ||
|
||
|
||
async function calculateClmmApr() { | ||
const poolId = '' | ||
|
||
const poolAccountInfo = await connection.getAccountInfo(new PublicKey(poolId)) | ||
|
||
if (poolAccountInfo === null) throw Error('get pool account data error') | ||
|
||
const mintPrice: { [mint: string]: number } = {} | ||
for (const [mint, price] of Object.entries(await (await fetch(ENDPOINT + RAYDIUM_MAINNET_API.price)).json()) as [string, number][]) mintPrice[mint] = price | ||
|
||
const poolApiInfo: { [poolId: string]: ApiClmmPoolsItem } = {} | ||
for (const item of (await (await fetch(ENDPOINT + RAYDIUM_MAINNET_API.clmmPools)).json()).data) poolApiInfo[item.id] = item | ||
|
||
const apiPoolInfo = poolApiInfo[poolId] | ||
if (apiPoolInfo === undefined) throw Error('api pool info check error') | ||
|
||
const poolInfo = PoolInfoLayout.decode(poolAccountInfo.data) | ||
|
||
const chainTime = await connection.getBlockTime(await connection.getSlot()) | ||
if (chainTime === null) throw Error('get chain time error') | ||
|
||
const formatRewardInfo: { | ||
mint: string, | ||
price: number, | ||
sendCountYear: number, | ||
sendCountYearToU: number, | ||
tvl: number, | ||
apr: number, | ||
}[] = [] | ||
|
||
for (const rewardInfo of poolInfo.rewardInfos) { | ||
if (rewardInfo.tokenMint.equals(PublicKey.default)) continue | ||
|
||
const rewardVaultAdress = rewardInfo.tokenVault | ||
const rewardVaultAccount = await connection.getParsedAccountInfo(rewardVaultAdress) | ||
const rewardVaultAccountData = rewardVaultAccount.value?.data as ParsedAccountData | ||
if (rewardVaultAccountData.program !== 'spl-token') continue | ||
|
||
const rewardPerSecond = (rewardInfo.openTime.toNumber() < chainTime && rewardInfo.endTime.toNumber() > chainTime) ? MathUtil.x64ToDecimal(rewardInfo.emissionsPerSecondX64) : new Decimal(0) | ||
|
||
const sendCountYear = new Decimal(rewardPerSecond.mul(3600 * 24 * 365).toString()).div(10 ** rewardVaultAccountData.parsed.info.tokenAmount.decimals) | ||
const sendCountYearToU = sendCountYear.mul(mintPrice[rewardVaultAccountData.parsed.info.mint] ?? 0) | ||
|
||
const tvl = apiPoolInfo.tvl | ||
|
||
formatRewardInfo.push({ | ||
mint: rewardVaultAccountData.parsed.info.mint, | ||
price: mintPrice[rewardVaultAccountData.parsed.info.mint] ?? 0, | ||
sendCountYear: sendCountYear.toNumber(), | ||
sendCountYearToU: sendCountYearToU.toNumber(), | ||
tvl, | ||
apr: tvl !== 0 ? sendCountYearToU.div(tvl).toNumber() : 0, | ||
}) | ||
} | ||
|
||
console.log(formatRewardInfo) | ||
} | ||
|
||
calculateClmmApr() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { FARM_STATE_LAYOUT_V3, FARM_STATE_LAYOUT_V5, FARM_STATE_LAYOUT_V6 } from "@raydium-io/raydium-sdk" | ||
import { ParsedAccountData, PublicKey } from "@solana/web3.js" | ||
import { BN } from "bn.js" | ||
import Decimal from "decimal.js" | ||
import { ENDPOINT, PROGRAMIDS, RAYDIUM_MAINNET_API, connection } from "../config" | ||
|
||
|
||
async function calculateFarmApr() { | ||
const poolId = '' | ||
|
||
const poolAccountInfo = await connection.getAccountInfo(new PublicKey(poolId)) | ||
|
||
if (poolAccountInfo === null) throw Error('get pool account data error') | ||
|
||
const mintPrice: { [mint: string]: number } = {} | ||
for (const [mint, price] of Object.entries(await (await fetch(ENDPOINT + RAYDIUM_MAINNET_API.price)).json()) as [string, number][]) mintPrice[mint] = price | ||
|
||
const poolTvl: { [poolId: string]: number } = {} | ||
for (const info of (await (await fetch(ENDPOINT + RAYDIUM_MAINNET_API.farmApr)).json()).data) poolTvl[info.id] = info.tvl | ||
|
||
const rewardInfo: { mint: string, price: number, sendCountYear: number, sendCountYearToU: number, tvl: number, apr: number }[] = [] | ||
|
||
switch (poolAccountInfo.owner.toString()) { | ||
case PROGRAMIDS.FarmV3.toString(): | ||
case PROGRAMIDS.FarmV5.toString(): { | ||
const layout = PROGRAMIDS.FarmV3.toString() === poolAccountInfo.owner.toString() ? FARM_STATE_LAYOUT_V3 : FARM_STATE_LAYOUT_V5 | ||
const poolInfo = layout.decode(poolAccountInfo.data) | ||
|
||
const poolVaultAccount = await connection.getParsedAccountInfo(poolInfo.lpVault) | ||
const poolVaultAccountData = poolVaultAccount.value?.data as ParsedAccountData | ||
if (poolVaultAccountData.program !== 'spl-token') break | ||
|
||
for (const itemRewardInfo of poolInfo.rewardInfos) { | ||
const rewardVaultAdress = itemRewardInfo.rewardVault | ||
const rewardVaultAccount = await connection.getParsedAccountInfo(rewardVaultAdress) | ||
const rewardVaultAccountData = rewardVaultAccount.value?.data as ParsedAccountData | ||
if (rewardVaultAccountData.program !== 'spl-token') continue | ||
|
||
const sendCountYear = new Decimal(itemRewardInfo.perSlotReward.mul(new BN(2.5 * 3600 * 24 * 365)).toString()).div(10 ** rewardVaultAccountData.parsed.info.tokenAmount.decimals) // one slot -> 400ms | ||
const sendCountYearToU = sendCountYear.mul(mintPrice[rewardVaultAccountData.parsed.info.mint] ?? 0) | ||
|
||
const tvl = poolTvl[poolId] !== undefined ? poolTvl[poolId] : poolVaultAccountData.parsed.info.tokenAmount.uiAmount * (mintPrice[poolVaultAccountData.parsed.info.mint] ?? 0) | ||
|
||
rewardInfo.push({ | ||
mint: rewardVaultAccountData.parsed.info.mint, | ||
price: mintPrice[rewardVaultAccountData.parsed.info.mint] ?? 0, | ||
sendCountYear: sendCountYear.toNumber(), | ||
sendCountYearToU: sendCountYearToU.toNumber(), | ||
tvl, | ||
apr: tvl !== 0 ? sendCountYearToU.div(tvl).toNumber() : 0, | ||
}) | ||
} | ||
break | ||
} | ||
case PROGRAMIDS.FarmV6.toString(): { | ||
const layout = FARM_STATE_LAYOUT_V6 | ||
const poolInfo = layout.decode(poolAccountInfo.data) | ||
|
||
const chainTime = await connection.getBlockTime(await connection.getSlot()) | ||
if (chainTime === null) throw Error('get chain time error') | ||
|
||
const poolVaultAccount = await connection.getParsedAccountInfo(poolInfo.lpVault) | ||
const poolVaultAccountData = poolVaultAccount.value?.data as ParsedAccountData | ||
if (poolVaultAccountData.program !== 'spl-token') break | ||
|
||
for (const itemRewardInfo of poolInfo.rewardInfos) { | ||
const rewardVaultAdress = itemRewardInfo.rewardVault | ||
const rewardVaultAccount = await connection.getParsedAccountInfo(rewardVaultAdress) | ||
const rewardVaultAccountData = rewardVaultAccount.value?.data as ParsedAccountData | ||
if (rewardVaultAccountData.program !== 'spl-token') continue | ||
|
||
const rewardPerSecond = (itemRewardInfo.rewardOpenTime.toNumber() < chainTime && itemRewardInfo.rewardEndTime.toNumber() > chainTime) ? itemRewardInfo.rewardPerSecond : new BN(0) | ||
|
||
const sendCountYear = new Decimal(rewardPerSecond.mul(new BN(3600 * 24 * 365)).toString()).div(10 ** rewardVaultAccountData.parsed.info.tokenAmount.decimals) | ||
const sendCountYearToU = sendCountYear.mul(mintPrice[rewardVaultAccountData.parsed.info.mint] ?? 0) | ||
|
||
const tvl = poolTvl[poolId] !== undefined ? poolTvl[poolId] : poolVaultAccountData.parsed.info.tokenAmount.uiAmount * (mintPrice[poolVaultAccountData.parsed.info.mint] ?? 0) | ||
|
||
rewardInfo.push({ | ||
mint: rewardVaultAccountData.parsed.info.mint, | ||
price: mintPrice[rewardVaultAccountData.parsed.info.mint] ?? 0, | ||
sendCountYear: sendCountYear.toNumber(), | ||
sendCountYearToU: sendCountYearToU.toNumber(), | ||
tvl, | ||
apr: tvl !== 0 ? sendCountYearToU.div(tvl).toNumber() : 0, | ||
}) | ||
} | ||
break | ||
} | ||
default: | ||
throw Error('program Id check error') | ||
} | ||
console.log(rewardInfo) | ||
} |