Along with percentage of ownership, positions also determine the rewards and fees earned by the liquidity providers for their participation. We can also find out the fees claimed by the liquidity provider. This again involves two simple steps:
We fetch all the position address for the liquidity provider (or the user)
Once we have the position address, we can fetch all transactions for each position address, and look for transactions of the 'CLAIMFEE' type. The actions array in each of these parsed (by SHYFT) 'CLAIMFEE' transactions will contain the details of the fees claimed.
You can directly copy paste this code on replit and see it in action.
The above function getClaimfeeDetails can also be used to fetch all claim rewards when only the position address in known.
import { ShyftSdk,Network } from"@shyft-to/js";constSHYFT_API_KEY="YOUR_SHYFT_API_KEY";constshyft=newShyftSdk({ apiKey:SHYFT_API_KEY, network:Network.Mainnet });asyncfunctiongetClaimfeeDetails(positionAddress:string) {let genesisTxnReached =false;let claimFeeTxns:any[] = [];let lastSignature =undefined;while (!genesisTxnReached) {consttransactions:any=awaitshyft.transaction.history({ account: positionAddress, network:Network.Mainnet, txNum:10, beforeTxSignature: lastSignature });transactions.map((txn:any) => {if(txn.type ==="CLAIMFEE")claimFeeTxns.push(txn); });if(transactions.length<10){ genesisTxnReached =true;break; } lastSignature = transactions[transactions.length-1].signatures[0]; }constamountClaimedDetails:any= [];claimFeeTxns.map((claimFeeTxn) => {consttokenX=claimFeeTxn.actions[0].info.tokenXMint;consttokenY=claimFeeTxn.actions[0].info.tokenYMint;let eachAddedTxn:any= {"txn_id":claimFeeTxn.signatures[0],"onchain_timestamp":claimFeeTxn.timestamp, };claimFeeTxn.actions.map((action:any) => {if(action.type ==="TOKEN_TRANSFER"){if(action.info.token_address === tokenX){ eachAddedTxn = {...eachAddedTxn,"tokenX_amount":action.info.amount_raw,"tokenX_address":action.info.token_address } }if(action.info.token_address === tokenY){ eachAddedTxn = {...eachAddedTxn,"tokenY_amount":action.info.amount_raw,"tokenY_address":action.info.token_address } }if(eachAddedTxn.tokenX_amount &&eachAddedTxn.tokenY_amount)amountClaimedDetails.push(eachAddedTxn); } }) })console.log(amountClaimedDetails);}// getClaimfeeDetails("CFUjqVgyzNfW88FxR3npGBNoPsyceec8CU3778rJ4F8b")asyncfunctiongetPositionLiquidityDetails(ownerAddress:string) {//querying both position and positionV2 for the owner, or user walletconstoperationsDoc=` query MyQuery { meteora_dlmm_PositionV2( where: {owner: {_eq: ${JSON.stringify(ownerAddress)}}} ) { lastUpdatedAt lbPair owner pubkey } meteora_dlmm_Position( where: {owner: {_eq: ${JSON.stringify(ownerAddress)}}} ) { lastUpdatedAt lbPair owner pubkey } } `; //you can cherrypick the fields as per your requirementconstresult=awaitfetch( `https://programs.shyft.to/v0/graphql/accounts?api_key=${SHYFT_API_KEY}&network=mainnet-beta`, //SHYFT's GQL endpoint
{ method:"POST", body:JSON.stringify({ query: operationsDoc, variables: {}, operationName:"MyQuery", }), } );const { errors,data } =awaitresult.json();//adding a delay of 2 seconds to avoid rate limiting, only for free API Keys.awaitnewPromise((resolve) =>setTimeout(resolve,2000));if (data.meteora_dlmm_Position.length>0) {for (let index =0; index <data.meteora_dlmm_Position.length; index++) {constposition=data.meteora_dlmm_Position[index];//get fee claims for each positionawaitgetClaimfeeDetails(position.pubkey) } }//adding a delay of 2 seconds to avoid rate limiting, only for free API Keys.awaitnewPromise((resolve) =>setTimeout(resolve,2000));if (data.meteora_dlmm_PositionV2.length>0) {for (let index =0; index <data.meteora_dlmm_PositionV2.length; index++) {constposition=data.meteora_dlmm_PositionV2[index];//get fee claims for each positionV2awaitgetClaimfeeDetails(position.pubkey) } }}getPositionLiquidityDetails("5sJKcYqCWNPJ25PriinfeH7PbFsHxzQhe8kspg2UFexK")