Zum Hauptinhalt springen

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.Englische Version ansehen →
Wallets, die Raydium integrieren, müssen pro Benutzer typischerweise vier Fragen beantworten: In welchen Pools hält dieser Benutzer LP-Positionen? Welche Positionen (CLMM-NFTs) hält er? In welchen Farms hat er Stakes? Wie viel ist das alles wert? Diese Seite dokumentiert die Antworten.

Raydium-Positionen erkennen

Classic LP-Tokens (CPMM, AMM v4)

Diese sehen aus wie jeder andere SPL-Token: Das ATA des Benutzers hält einen Kontostand. Eine Wallet zeigt dies normalerweise einfach als weiteren Token an. Um es als Raydium-LP-Position zu erkennen:
  1. Aufzählung der Token-Konten des Benutzers: connection.getParsedTokenAccountsByOwner(user, { programId: TOKEN_PROGRAM_ID }).
  2. Für jede Mint, prüfen Sie Raydiums Mint-Liste: GET https://api-v3.raydium.io/pools/info/lps?lps=<LP_MINT>,... (bis zu ~50 LP-Mints pro Aufruf bündeln).
  3. Für Mints, die passen, gibt die API die Pool-Referenz zurück. Verwenden Sie sie, um den Token-denominierten Wert der Position zu berechnen:
token_a_owned = user_lp_balance * poolReserves.A / lpMint.supply
token_b_owned = user_lp_balance * poolReserves.B / lpMint.supply
usd_value     = token_a_owned * priceA_usd + token_b_owned * priceB_usd
Zeigen Sie sowohl den LP-Saldo als auch die unwrapped-Beträge an — Benutzer denken in zugrundeliegenden Tokens, nicht in LP-Einheiten.

CLMM-Position-NFTs

CLMM-Positionen sind NFTs. Der PersonalPositionState PDA jeder Position wird aus dem NFT-Mint abgeleitet. Zum Erkennen:
  1. Aufzählung der NFTs des Benutzers. Für Legacy-Metaplex-NFTs: Filtern Sie Token-Konten auf solche mit Supply 1 und Dezimalzahlen 0.
  2. Für jede NFT-Mint, versuchen Sie, den PersonalPositionState PDA abzuleiten:
import { CLMM_PROGRAM_ID } from "@raydium-io/raydium-sdk-v2";

const [positionPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("position"), nftMint.toBuffer()],
  CLMM_PROGRAM_ID,
);

const accountInfo = await connection.getAccountInfo(positionPda);
if (!accountInfo || !accountInfo.owner.equals(CLMM_PROGRAM_ID)) return null;
// Es ist eine Raydium CLMM-Position — dekodieren.
  1. Dekodieren über raydium.clmm.getPositionInfo({ positionPda }), um zu erhalten:
    • poolId → Pool abrufen, um Mints zu auflösen
    • tickLower, tickUpper → Bereich anzeigen
    • liquidity, tokensOwedA/B → Positionswert + ausstehende Gebühren berechnen
    • rewardInfos → ausstehende Belohnungen pro Stream
  2. Für Position-NFTs, die unter Token-2022 ausgegeben wurden (OpenPositionWithToken22Nft), ist das Programm des NFT-Mint Token-2022 statt SPL Token. Zählen Sie beide auf, wenn Sie scannen.

Farm-Stakes

Farm v3 / v5 / v6 haben jeweils einen pro-Benutzer Ledger PDA. Ableitungen:
// Versuchen Sie alle drei Farm-Versionen für jede mögliche Farm-Interaktion des Benutzers.
// Günstigster Ansatz: Fragen Sie zuerst die API, die alle Benutzer-Positionen indiziert hat.

const r = await fetch(
  `https://api-v3.raydium.io/positions/staking?wallet=${user.toBase58()}`
).then(r => r.json());

for (const s of r.data.stakings) {
  // s.farmId, s.stakedAmount, s.pendingRewards[], s.poolApr, ...
}
Für Wallets, die vollständige On-Chain-Erkennung bevorzugen: Durchlaufen Sie mögliche UserLedger PDAs, indem Sie den Benutzer mit einer kuratierten Liste von „wahrscheinlichen” Farm-IDs hashen. Das vollständige Aufzählen aller Farm-IDs ist unpraktisch (es existieren Tausende); verwenden Sie die API.

Positionswert berechnen

CPMM / AMM v4 LP

const poolInfo = await raydium.<type>.getPoolInfoFromRpc({ poolId });
const myShare  = userLpBalance / poolInfo.lpMint.supply;
const tokensA  = BigInt(poolInfo.mintAmountA) * BigInt(userLpBalance)
                / BigInt(poolInfo.lpMint.supply);
const tokensB  = BigInt(poolInfo.mintAmountB) * BigInt(userLpBalance)
                / BigInt(poolInfo.lpMint.supply);
Dann multiplizieren Sie jedes mit dem USD-Preis der Mint (von raydium.token oder einem Price-Oracle).

CLMM-Position

const position = await raydium.clmm.getPositionInfo({ positionPda });
const pool     = await raydium.clmm.getPoolInfoFromRpc({ poolId: position.poolId });

const { amountA, amountB } = PoolUtils.getAmountsFromLiquidity({
  sqrtPriceX64:  pool.sqrtPriceX64,
  tickLower:     position.tickLower,
  tickUpper:     position.tickUpper,
  liquidity:     position.liquidity,
  slippage:      0,  // zur Anzeige, kein Slippage
});

// Ausstehende Gebühren — separat als „nicht eingezogen" anzeigen
const fees = {
  A: position.tokenFeesOwedA,
  B: position.tokenFeesOwedB,
};

// Ausstehende Belohnungen — ein CLMM-Pool hat 0–3 Reward-Streams.
const rewards = position.rewardInfos.map(r => ({
  mint:          r.rewardMint,
  rewardAmount:  r.rewardAmountOwed,
}));
Rendern Sie als:
  • Liquiditätswert (aktueller Preis)
  • Nicht eingezogene Gebühren
  • Ausstehende Belohnungen pro Stream
  • Bereich: [tickLower_price, tickUpper_price] mit einer visuellen Leiste, die zeigt, ob der aktuelle Preis im Bereich liegt

Farm-Stake

// Die API-Antwort enthält bereits ausstehende Belohnungen; verwenden Sie diese direkt.
const apr       = stakingFarm.apr;               // %, annualisiert
const staked    = stakingFarm.stakedAmount;      // kleinste Einheiten der Staking-Mint
const rewards   = stakingFarm.pendingRewards;    // Array von { mint, amount }
Für On-Chain-Berechnung spiegeln Sie die Farm-Rechnungslegung wider:
pending_reward_i = user.deposited
                 * farm.reward_per_share_x64[i] / 2^64
                 - user.reward_debts[i]
Stellen Sie sicher, dass Sie reward_per_share_x64 mit der Lazy-Update-Formel aktualisieren, bevor Sie berechnen (verstrichene Zeit × Emissionsrate ÷ total_staked).

Transaktionssimulation für Vorschau

Bevor ein Benutzer signiert, zeigen Wallets normalerweise die Saldoänderungen vor. Verwenden Sie simulateTransaction:
const sim = await connection.simulateTransaction(tx, {
  sigVerify: false,
  commitment: "confirmed",
  accounts: {
    encoding: "base64",
    addresses: [userTokenAtaA, userTokenAtaB, userLpAta].map(a => a.toBase58()),
  },
});

// Dekodieren Sie jeden zurückgegebenen Kontosaldo und vergleichen Sie mit den Vortransaktionssalden.
for (const [i, acctData] of sim.value.accounts!.entries()) {
  const newBalance = decodeTokenAccount(acctData!.data[0]).amount;
  // mit Vortransaktionssaldo vergleichen, Δ anzeigen
}
Der Parameter accounts fordert den Validator auf, den Post-Simulations-Kontostatus für aufgelistete Adressen zurückzugeben. Viel genauer, als zu versuchen, die Saldoänderung allein aus der Anweisungsform vorherzusagen.

Simulations-Fallstricke

  • CLMM-Swaps benötigen gültige Tick-Arrays. Wenn die Eingabegröße des Benutzers in ein nicht initialisiertes Tick-Array übergehen würde, wird die Simulation rückgängig gemacht (wie auch die Ausführung). Zeigen Sie dies deutlich in der UI.
  • Priority Fee. Simulation wird ohne die angewendeten Compute-Budget-Anweisungen ausgeführt. Für eine große Transaktion, die das Standard-200k CU überschreiten würde, schlägt die Simulation fehl, aber die tatsächliche Ausführung mit einem expliziten CU-Limit erfolgreich. Setzen Sie das CU-Limit auch auf der simulierten Tx.
  • Frischer Blockhash. Simulation verwendet den aktuellen Blockhash; wenn das Signieren >60s dauert, wird die Tx ungültig. Simulieren Sie neu, wenn der Benutzer zögert.

Token-2022-Anzeige

Token unter dem Token-2022-Programm sollten in der Token-Liste der Wallet als solche gekennzeichnet werden, da sie unterschiedliche Risikoflächen haben:
  • Transfer-Fee-Mints: Zeigen Sie die aktuelle transferFeeBasisPoints als „Transfer Fee: X%” neben dem Saldo an. Warnen Sie beim Empfang — Benutzer könnten nicht realisieren, dass sie weniger erhalten, als der Sender gesendet hat.
  • Transfer-Hook-Mints: Machen Sie die Hook-Programm-ID sichtbar. Ein böswilliger Hook kann ausgehende Transfers blockieren; Benutzer sollten überprüfen, dass der Hook der ist, den sie erwarten.
  • Non-Transferable-Mints: Zeigen Sie „Non-transferable” an und deaktivieren Sie Swap/Senden. Dies sind typischerweise Soulbound-Tokens oder Credentials.
  • Interest-Bearing-Mints: Der UI-Saldo, der aus TokenAccount.amount abgeleitet ist, spiegelt nicht aufgelaufene Zinsen wider. Verwenden Sie amountToUiAmount aus @solana/spl-token (der den Skalierungsfaktor anwendet) für den angezeigten Wert.

Farm-APR-Anzeige

Die APR, die Benutzern angezeigt wird, sollte alle aktiven Reward-Streams kombinieren, in USD umgerechnet und annualisiert:
let apr = 0;
for (const r of farm.rewardInfos) {
  if (r.rewardState !== 1) continue;   // überspringe nicht-laufende
  const annualRewardTokens = Number(r.emissionPerSecond) * 86400 * 365 / 1e<decimals>;
  const annualRewardValue  = annualRewardTokens * priceUsd(r.rewardMint);
  const tvlValue           = Number(farm.totalStaked) * priceUsd(farm.stakingMint) / 1e<decimals>;
  apr += annualRewardValue / tvlValue;
}
Zeigen Sie als APR: X.Y% an. Wenn die Staking-Mint ein LP-Token ist, berechnen Sie auch den zugrundeliegenden LP-Basis-Fee-APR und kennzeichnen Sie die Summe als „Total APR” oder „APR + Gebühren”.

Hinweise

Quellen:
  • Raydium SDK v2 — Position/Farm-Helfer.
  • Benutzer-Positions-Endpunkte auf api-v3.raydium.io.