1.2.251 • Published 8 months ago

test-r-sdk v1.2.251

Weekly downloads
-
License
GPL-3.0
Repository
github
Last release
8 months ago

Raydium SDK

npm

An SDK for building applications on top of Raydium.

Installation

Yarn

$ yarn add @raydium-io/raydium-sdk

npm

$ npm install @raydium-io/raydium-sdk --save

Hosting JSON files

Tokens List

Token Icons

  • /icons/{mint}.png

Liquidity Pools List

Includes all pubkeys that build transaction need

Example of parse pool info

import { Connection, PublicKey } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import {
  TokenAccount,
  SPL_ACCOUNT_LAYOUT,
  LIQUIDITY_STATE_LAYOUT_V4,
} from "@raydium-io/raydium-sdk";
import { OpenOrders } from "@project-serum/serum";
import BN from "bn.js";

async function getTokenAccounts(connection: Connection, owner: PublicKey) {
  const tokenResp = await connection.getTokenAccountsByOwner(owner, {
    programId: TOKEN_PROGRAM_ID,
  });

  const accounts: TokenAccount[] = [];
  for (const { pubkey, account } of tokenResp.value) {
    accounts.push({
      pubkey,
      accountInfo: SPL_ACCOUNT_LAYOUT.decode(account.data),
    });
  }

  return accounts;
}

// raydium pool id can get from api: https://api.raydium.io/v2/sdk/liquidity/mainnet.json
const SOL_USDC_POOL_ID = "58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2";
const OPENBOOK_PROGRAM_ID = new PublicKey(
  "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX"
);

export async function parsePoolInfo() {
  const connection = new Connection({mainnet rpc node}, "confirmed");
  const owner = new PublicKey("VnxDzsZ7chE88e9rB6UKztCt2HUwrkgCTx8WieWf5mM");

  const tokenAccounts = await getTokenAccounts(connection, owner);

  // example to get pool info
  const info = await connection.getAccountInfo(new PublicKey(SOL_USDC_POOL_ID));
  if (!info) return;

  const poolState = LIQUIDITY_STATE_LAYOUT_V4.decode(info.data);
  const openOrders = await OpenOrders.load(
    connection,
    poolState.openOrders,
    OPENBOOK_PROGRAM_ID // OPENBOOK_PROGRAM_ID(marketProgramId) of each pool can get from api: https://api.raydium.io/v2/sdk/liquidity/mainnet.json
  );

  const baseDecimal = 10 ** poolState.baseDecimal.toNumber(); // e.g. 10 ^ 6
  const quoteDecimal = 10 ** poolState.quoteDecimal.toNumber();

  const baseTokenAmount = await connection.getTokenAccountBalance(
    poolState.baseVault
  );
  const quoteTokenAmount = await connection.getTokenAccountBalance(
    poolState.quoteVault
  );

  const basePnl = poolState.baseNeedTakePnl.toNumber() / baseDecimal;
  const quotePnl = poolState.quoteNeedTakePnl.toNumber() / quoteDecimal;

  const openOrdersBaseTokenTotal =
    openOrders.baseTokenTotal.toNumber() / baseDecimal;
  const openOrdersQuoteTokenTotal =
    openOrders.quoteTokenTotal.toNumber() / quoteDecimal;

  const base =
    (baseTokenAmount.value?.uiAmount || 0) + openOrdersBaseTokenTotal - basePnl;
  const quote =
    (quoteTokenAmount.value?.uiAmount || 0) +
    openOrdersQuoteTokenTotal -
    quotePnl;

  const denominator = new BN(10).pow(poolState.baseDecimal);

  const addedLpAccount = tokenAccounts.find((a) =>
    a.accountInfo.mint.equals(poolState.lpMint)
  );

  console.log(
    "SOL_USDC pool info:",
    "pool total base " + base,
    "pool total quote " + quote,

    "base vault balance " + baseTokenAmount.value.uiAmount,
    "quote vault balance " + quoteTokenAmount.value.uiAmount,

    "base tokens in openorders " + openOrdersBaseTokenTotal,
    "quote tokens in openorders  " + openOrdersQuoteTokenTotal,

    "base token decimals " + poolState.baseDecimal.toNumber(),
    "quote token decimals " + poolState.quoteDecimal.toNumber(),
    "total lp " + poolState.lpReserve.div(denominator).toString(),

    "addedLpAmount " +
      (addedLpAccount?.accountInfo.amount.toNumber() || 0) / baseDecimal
  );
}

parsePoolInfo();

Farm/Staking Pools List

Includes all pubkeys that build transaction need

Example of parse farm info

import { Connection, PublicKey } from "@solana/web3.js";
import { Farm } from "@raydium-io/raydium-sdk";
import {
  JsonPairItemInfo,
  FarmPoolsJsonFile,
  FarmPoolJsonInfo,
  TokenInfo,
} from "./types";
import axios from "axios";
import Decimal from "decimal.js";

// raydium farm id can get from api: https://api.raydium.io/v2/sdk/farm-v2/mainnet.json
const SOL_USDC_FARM_ID = "GUzaohfNuFbBqQTnPgPSNciv3aUvriXYjQduRE3ZkqFw";

export async function demoFarm() {
  const connection = new Connection({mainnet rpc node}, "confirmed");
  const owner = new PublicKey("VnxDzsZ7chE88e9rB6UKztCt2HUwrkgCTx8WieWf5mM");

  console.log("fetching farms");
  const { data: farmData } = await axios.get<FarmPoolsJsonFile>(
    "https://api.raydium.io/v2/sdk/farm-v2/mainnet.json"
  );

  console.log("fetching pairs");
  const { data: pairData } = await axios.get<JsonPairItemInfo[]>(
    "https://api.raydium.io/v2/main/pairs"
  );

  const pairApr = Object.fromEntries(
    pairData.map((i) => [
      i.ammId,
      { apr30d: i.apr30d, apr7d: i.apr7d, apr24h: i.apr24h },
    ])
  );

  console.log("fetching liquidity");
  const { data: liquidityData } = await axios.get<{
    official: any[];
    unOfficial: any[];
  }>("https://api.raydium.io/v2/sdk/liquidity/mainnet.json");

  const allLiquidity = [...liquidityData.official, ...liquidityData.unOfficial];

  console.log("fetching token data");
  const { data: tokenData } = await axios.get<{
    official: TokenInfo[];
    unOfficial: TokenInfo[];
  }>("https://api.raydium.io/v2/sdk/token/raydium.mainnet.json");

  const allToken: Map<string, TokenInfo> = [
    ...tokenData.official,
    ...tokenData.unOfficial,
  ].reduce((acc, cur) => {
    acc.set(cur.mint, cur);
    return acc;
  }, new Map());

  console.log("fetching token prices");
  const { data: tokenPrices } = await axios.get<{ [key: string]: number }>(
    "https://api.raydium.io/v2/main/price"
  );

  console.log("fetching chain time");
  const { data: chainTimeData } = await axios.get<{
    chainTime: number;
    offset: number;
  }>("https://api.raydium.io/v2/sdk/token/raydium.mainnet.json");

  const currentBlockChainDate =
    chainTimeData.chainTime * 1000 + chainTimeData.offset * 1000;

  const allFarms: FarmPoolJsonInfo[] = Object.keys(farmData).reduce(
    // @ts-ignore
    (acc, cur) => [...acc.concat(farmData[cur])],
    []
  );

  const farmInfo = allFarms.find((farm) => farm.id === SOL_USDC_FARM_ID)!;
  const pairInfo = pairData.find((p) => p.lpMint === farmInfo.lpMint)!;
  const liquidityInfo = allLiquidity.find((p) => p.lpMint === farmInfo.lpMint)!;

  const farmInfoWithKeys = {
    ...farmInfo,
    id: new PublicKey(farmInfo.id),
    programId: new PublicKey(farmInfo.programId),
    baseMint: new PublicKey(farmInfo.baseMint),
    quoteMint: new PublicKey(farmInfo.quoteMint),
    lpMint: new PublicKey(farmInfo.lpMint),
    authority: new PublicKey(farmInfo.authority),
    lpVault: new PublicKey(farmInfo.lpVault),
    rewardInfos: farmInfo.rewardInfos.map((r) => ({
      ...r,
      rewardMint: new PublicKey(r.rewardMint),
      rewardVault: new PublicKey(r.rewardVault),
    })),
  };

  console.log("decode farm data");
  const parsedFarmInfo = (
    await Farm.fetchMultipleInfoAndUpdate({
      connection,
      pools: [farmInfoWithKeys],
      owner,
      config: { commitment: "confirmed" },
    })
  )[SOL_USDC_FARM_ID];

  const tvl = new Decimal(parsedFarmInfo.lpVault.amount.toString())
    .div(10 ** liquidityInfo.lpDecimals)
    .mul(pairInfo.lpPrice || 0);

  const samples = await connection.getRecentPerformanceSamples(4);
  const slotList = samples.map((item) => item.numSlots);
  const blockSlotCountForSecond =
    slotList.reduce((a, b) => a + b, 0) / slotList.length / 60;

  const rewardsApr = parsedFarmInfo.state.rewardInfos.map((r: any, idx) => {
    if (farmInfo.version === 6) {
      const { rewardPerSecond, rewardOpenTime, rewardEndTime, rewardMint } = r;
      const isRewardBeforeStart =
        rewardOpenTime.toNumber() * 1000 < currentBlockChainDate;
      const isRewardAfterEnd =
        rewardEndTime.toNumber() * 1000 > currentBlockChainDate;
      if (isRewardBeforeStart || isRewardAfterEnd) return 0;

      if (!rewardMint) return 0;
      const rewardPrice = tokenPrices[rewardMint.toString()] || 0;
      if (!rewardPrice) return 0;
      const rewardToken = allToken.get(rewardMint.toString())!;
      if (!rewardToken) return 0;

      const reward = new Decimal(rewardPerSecond.toString())
        .div(10 ** rewardToken.decimals)
        .mul(60 * 60 * 24 * 365)
        .mul(rewardPrice);

      const tvl = new Decimal(parsedFarmInfo.lpVault.amount.toString())
        .div(10 ** liquidityInfo.lpDecimals)
        .mul(pairInfo.lpPrice || 0);

      const apr = reward.div(tvl);

      return apr.toNumber();
    }

    const rewardMint = farmInfo.rewardInfos[idx].rewardMint;
    const rewardPrice = tokenPrices[rewardMint] || 0;
    const rewardToken = allToken.get(rewardMint)!;
    const reward = new Decimal(r.perSlotReward.toString())
      .div(10 ** rewardToken.decimals)
      .mul(blockSlotCountForSecond * 60 * 60 * 24 * 365)
      .mul(rewardPrice);

    const apr = reward.div(tvl);

    return apr.toNumber();
  });

  const totalApr24h = new Decimal(rewardsApr.reduce((acc, cur) => acc + cur, 0))
    .mul(100)
    .add(pairApr[liquidityInfo.id].apr24h);

  const userDeposited = new Decimal(
    parsedFarmInfo.ledger?.deposited.toString() || 0
  ).div(10 ** liquidityInfo.lpDecimals);

  console.log({
    userDeposited: userDeposited.toString(),
    tvl: tvl.toString(),
    totalApr24h: totalApr24h.toString(),
    rewards: rewardsApr
      .filter((apr) => apr > 0)
      .map((apr, idx) => ({
        apr: apr * 100 + "%",
        rewardToken: allToken.get(
          farmInfo.rewardInfos[idx].rewardMint ||
            // @ts-ignore
            parsedFarmInfo.state.rewardInfos[idx].rewardMint.toString()
        )!.symbol,
      })),
  });
}

demoFarm();
types
export interface JsonPairItemInfo {
  ammId: string;
  apr24h: number;
  apr7d: number;
  apr30d: number;
  fee7d: number;
  fee7dQuote: number;
  fee24h: number;
  fee24hQuote: number;
  fee30d: number;
  fee30dQuote: number;
  liquidity: number;
  lpMint: string;
  lpPrice: number | null;
  market: string;
  name: string;
  official: boolean;
  price: number;
  tokenAmountCoin: number;
  tokenAmountLp: number;
  tokenAmountPc: number;
  volume7d: number;
  volume7dQuote: number;
  volume24h: number;
  volume24hQuote: number;
  volume30d: number;
  volume30dQuote: number;
}

export interface APIRewardInfo {
  rewardMint: string;
  rewardVault: string;
  rewardOpenTime: number;
  rewardEndTime: number;
  rewardPerSecond: string | number;
  rewardSender?: string;
  rewardType: "Standard SPL" | "Option tokens";
}

export interface FarmPoolJsonInfo {
  id: string;
  lpMint: string;
  lpVault: string;

  baseMint: string;
  quoteMint: string;
  name: string;

  version: number;
  programId: string;

  authority: string;
  creator?: string;
  rewardInfos: APIRewardInfo[];
  upcoming: boolean;

  rewardPeriodMin?: number; // v6 '7-90 days's     7 * 24 * 60 * 60 seconds
  rewardPeriodMax?: number; // v6 '7-90 days's     90 * 24 * 60 * 60 seconds
  rewardPeriodExtend?: number; // v6 'end before 72h's    72 * 60 * 60 seconds

  local: boolean; // only if it is in localstorage(create just by user)
  category: "stake" | "raydium" | "fusion" | "ecosystem"; // add by UI for unify the interface
}

export type FarmPoolsJsonFile = {
  name: string;
  version: unknown;
  stake: Omit<FarmPoolJsonInfo, "category">[];
  raydium: Omit<FarmPoolJsonInfo, "category">[];
  fusion: Omit<FarmPoolJsonInfo, "category">[];
  ecosystem: Omit<FarmPoolJsonInfo, "category">[];
};

export interface TokenInfo {
  symbol: string;
  name: string;
  mint: string;
  decimals: number;
  extensions: {
    coingeckoId?: string;
  };
  icon: string;
  hasFreeze: number;
}

Program IDs

FunctionVersionMainnet
AMM / Liquidity4675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8
Farm / Staking3EhhTKczWMGQt46ynNeRX1WfeagwwJd7ufHvCDjRxjo5Q
Farm / Staking59KEPoZmtHUrBbhWN1v1KWLMkkvwY6WLtAVUCPRtRjP4z
AMM Route1routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS
Serum39xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin

Usage

Marshmallow

Full layout type inference

npm.io npm.io

Development

yarn install && yarn install-peers

Reference

1.2.251

8 months ago

1.2.250

8 months ago

1.2.211

10 months ago

1.2.210

10 months ago

1.2.213

10 months ago

1.2.212

10 months ago

1.2.215

10 months ago

1.2.214

10 months ago

1.2.217

10 months ago

1.2.216

10 months ago

1.2.208

10 months ago

1.2.207

10 months ago

1.2.209

10 months ago

1.2.222

10 months ago

1.2.221

10 months ago

1.2.224

10 months ago

1.2.223

10 months ago

1.2.226

10 months ago

1.2.225

10 months ago

1.2.228

10 months ago

1.2.227

10 months ago

1.2.220

10 months ago

1.2.219

10 months ago

1.2.218

10 months ago

1.2.233

9 months ago

1.2.232

9 months ago

1.2.235

9 months ago

1.2.234

9 months ago

1.2.237

9 months ago

1.2.236

9 months ago

1.2.239

9 months ago

1.2.238

9 months ago

1.2.231

9 months ago

1.2.230

9 months ago

1.2.229

9 months ago

1.2.244

9 months ago

1.2.243

9 months ago

1.2.246

9 months ago

1.2.245

9 months ago

1.2.248

9 months ago

1.2.247

9 months ago

1.2.249

9 months ago

1.2.240

9 months ago

1.2.242

9 months ago

1.2.241

9 months ago

1.2.200

10 months ago

1.2.202

10 months ago

1.2.201

10 months ago

1.2.204

10 months ago

1.2.203

10 months ago

1.2.206

10 months ago

1.2.205

10 months ago

1.2.189

11 months ago

1.2.188

11 months ago

1.2.185

11 months ago

1.2.187

11 months ago

1.2.186

11 months ago

1.2.199

10 months ago

1.2.192

10 months ago

1.2.191

10 months ago

1.2.194

10 months ago

1.2.193

10 months ago

1.2.196

10 months ago

1.2.195

10 months ago

1.2.198

10 months ago

1.2.197

10 months ago

1.2.190

11 months ago

1.2.147

1 year ago

1.2.146

1 year ago

1.2.149

1 year ago

1.2.148

1 year ago

1.2.156

1 year ago

1.2.155

1 year ago

1.2.158

1 year ago

1.2.157

1 year ago

1.2.159

1 year ago

1.2.150

1 year ago

1.2.152

1 year ago

1.2.151

1 year ago

1.2.154

1 year ago

1.2.153

1 year ago

1.2.167

1 year ago

1.2.166

1 year ago

1.2.169

1 year ago

1.2.168

1 year ago

1.2.161

1 year ago

1.2.160

1 year ago

1.2.163

1 year ago

1.2.162

1 year ago

1.2.165

1 year ago

1.2.164

1 year ago

1.2.178

1 year ago

1.2.177

1 year ago

1.2.179

1 year ago

1.2.170

1 year ago

1.2.172

1 year ago

1.2.171

1 year ago

1.2.174

1 year ago

1.2.173

1 year ago

1.2.176

1 year ago

1.2.175

1 year ago

1.2.181

1 year ago

1.2.180

1 year ago

1.2.183

1 year ago

1.2.182

1 year ago

1.2.184

1 year ago

1.2.134

1 year ago

1.2.133

1 year ago

1.2.136

1 year ago

1.2.135

1 year ago

1.2.138

1 year ago

1.2.137

1 year ago

1.2.139

1 year ago

1.2.130

1 year ago

1.2.132

1 year ago

1.2.131

1 year ago

1.2.81

2 years ago

1.2.82

2 years ago

1.2.80

2 years ago

1.2.85

2 years ago

1.2.86

2 years ago

1.2.83

2 years ago

1.2.84

2 years ago

1.2.89

2 years ago

1.2.87

2 years ago

1.2.88

2 years ago

1.2.144

1 year ago

1.2.141

1 year ago

1.2.140

1 year ago

1.2.143

1 year ago

1.2.142

1 year ago

1.2.92

2 years ago

1.2.93

2 years ago

1.2.90

2 years ago

1.2.91

2 years ago

1.2.96

2 years ago

1.2.97

2 years ago

1.2.94

2 years ago

1.2.95

2 years ago

1.2.98

2 years ago

1.2.99

2 years ago

1.2.79

2 years ago

1.2.101

2 years ago

1.2.100

2 years ago

1.2.103

2 years ago

1.2.102

2 years ago

1.2.105

2 years ago

1.2.104

2 years ago

1.2.107

2 years ago

1.2.106

2 years ago

1.2.112

1 year ago

1.2.111

1 year ago

1.2.114

1 year ago

1.2.113

1 year ago

1.2.116

1 year ago

1.2.115

1 year ago

1.2.118

1 year ago

1.2.117

1 year ago

1.2.110

2 years ago

1.2.109

2 years ago

1.2.123

1 year ago

1.2.122

1 year ago

1.2.125

1 year ago

1.2.124

1 year ago

1.2.127

1 year ago

1.2.126

1 year ago

1.2.129

1 year ago

1.2.128

1 year ago

1.2.121

1 year ago

1.2.120

1 year ago

1.2.119

1 year ago

1.2.78

2 years ago

1.2.77

2 years ago

1.2.76

2 years ago

1.2.75

2 years ago

1.2.74

2 years ago

1.2.73

2 years ago

1.2.72

2 years ago

1.2.71

2 years ago

1.2.70

2 years ago

1.2.69

2 years ago

1.2.68

2 years ago

1.2.67

2 years ago

1.2.66

2 years ago

1.2.65

2 years ago

1.2.64

2 years ago

1.2.63

2 years ago

1.2.62

2 years ago

1.2.61

2 years ago

1.2.60

2 years ago

1.2.59

2 years ago

1.2.58

2 years ago

1.2.57

2 years ago

1.2.56

2 years ago

1.2.55

2 years ago

1.2.54

2 years ago

1.2.53

2 years ago

1.2.52

2 years ago

1.2.51

2 years ago

1.2.50

2 years ago

1.2.49

2 years ago

1.2.47

2 years ago

1.2.46

2 years ago

1.2.45

2 years ago

1.2.44

2 years ago

1.2.43

2 years ago

1.2.42

2 years ago

1.2.41

2 years ago

1.2.40

2 years ago

1.2.39

2 years ago

1.2.38

2 years ago

1.2.37

2 years ago

1.2.36

2 years ago

1.2.35

2 years ago

1.2.34

2 years ago

1.2.33

2 years ago

1.2.32

2 years ago

1.2.31

2 years ago

1.2.30

2 years ago

1.2.29

2 years ago

1.2.27

2 years ago

1.2.26

2 years ago

1.2.25

2 years ago

1.2.23

2 years ago

1.2.22

2 years ago

1.2.21

2 years ago

1.2.20

2 years ago

1.2.19

2 years ago

1.2.18

2 years ago

1.2.17

2 years ago

1.2.16

2 years ago

1.2.15

2 years ago

1.2.14

2 years ago

1.2.13

2 years ago

1.2.12

2 years ago

1.2.11

2 years ago

1.2.10

2 years ago

1.2.9

2 years ago

1.2.8

2 years ago

1.2.7

2 years ago

1.2.6

2 years ago

1.2.5

2 years ago

1.2.4

2 years ago

1.2.3

2 years ago

1.2.2

2 years ago

1.1.0-beta.8

2 years ago

1.1.0-beta.7

2 years ago