diff --git a/README.md b/README.md index 568297f..8147ff7 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,19 @@ const signature = await stakeWithJup( ); ``` +### Fetch Token Price + +```typescript +import { fetchPrice } from 'solana-agent-kit'; + +const price = await fetchPrice( + agent, + 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN' // Token mint address +); + +console.log('Price in USDC:', price); +``` + ## API Reference ### Core Functions diff --git a/src/langchain/index.ts b/src/langchain/index.ts index a69568e..c4d506b 100644 --- a/src/langchain/index.ts +++ b/src/langchain/index.ts @@ -3,6 +3,7 @@ import { SolanaAgentKit } from "../index"; import { PublicKey } from "@solana/web3.js"; import { toJSON } from "../utils/toJSON"; import { create_image } from "../tools/create_image"; +import { fetchPrice } from "../tools/fetch_price"; export class SolanaBalanceTool extends Tool { name = "solana_balance"; @@ -63,7 +64,7 @@ export class SolanaTransferTool extends Tool { const tx = await this.solanaKit.transfer( recipient, parsedInput.amount, - mintAddress, + mintAddress ); return JSON.stringify({ @@ -101,7 +102,7 @@ export class SolanaDeployTokenTool extends Tool { input.decimals > 9) ) { throw new Error( - "decimals must be a number between 0 and 9 when provided", + "decimals must be a number between 0 and 9 when provided" ); } if ( @@ -158,7 +159,7 @@ export class SolanaDeployCollectionTool extends Tool { input.royaltyBasisPoints > 10000) ) { throw new Error( - "royaltyBasisPoints must be a number between 0 and 10000 when provided", + "royaltyBasisPoints must be a number between 0 and 10000 when provided" ); } if (input.creators) { @@ -168,7 +169,7 @@ export class SolanaDeployCollectionTool extends Tool { input.creators.forEach((creator: any, index: number) => { if (!creator.address || typeof creator.address !== "string") { throw new Error( - `creator[${index}].address is required and must be a string`, + `creator[${index}].address is required and must be a string` ); } if ( @@ -177,7 +178,7 @@ export class SolanaDeployCollectionTool extends Tool { creator.percentage > 100 ) { throw new Error( - `creator[${index}].percentage must be a number between 0 and 100`, + `creator[${index}].percentage must be a number between 0 and 100` ); } }); @@ -245,9 +246,7 @@ export class SolanaMintNFTTool extends Tool { const result = await this.solanaKit.mintNFT( new PublicKey(parsedInput.collectionMint), parsedInput.metadata, - parsedInput.recipient - ? new PublicKey(parsedInput.recipient) - : undefined, + parsedInput.recipient ? new PublicKey(parsedInput.recipient) : undefined ); return JSON.stringify({ @@ -291,7 +290,7 @@ export class SolanaTradeTool extends Tool { parsedInput.inputMint ? new PublicKey(parsedInput.inputMint) : new PublicKey("So11111111111111111111111111111111111111112"), - parsedInput.slippageBps, + parsedInput.slippageBps ); return JSON.stringify({ @@ -371,7 +370,7 @@ export class SolanaRegisterDomainTool extends Tool { const tx = await this.solanaKit.registerDomain( parsedInput.name, - parsedInput.spaceKB || 1, + parsedInput.spaceKB || 1 ); return JSON.stringify({ @@ -462,7 +461,7 @@ export class SolanaPumpfunTokenLaunchTool extends Tool { telegram: parsedInput.telegram, website: parsedInput.website, initialLiquiditySOL: parsedInput.initialLiquiditySOL, - }, + } ); return JSON.stringify({ @@ -600,6 +599,38 @@ export class SolanaStakeTool extends Tool { } } +/** + * Tool to fetch the price of a token in USDC + */ +export class SolanaFetchPriceTool extends Tool { + name = "solana_fetch_price"; + description = `Fetch the price of a given token in USDC. + + Inputs: + - tokenId: string, the mint address of the token, e.g., "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"`; + + constructor(private solanaKit: SolanaAgentKit) { + super(); + } + + async _call(input: string): Promise { + try { + const price = await fetchPrice(this.solanaKit, input.trim()); + return JSON.stringify({ + status: "success", + tokenId: input.trim(), + priceInUSDC: price, + }); + } catch (error: any) { + return JSON.stringify({ + status: "error", + message: error.message, + code: error.code || "UNKNOWN_ERROR", + }); + } + } +} + export function createSolanaTools(solanaKit: SolanaAgentKit) { return [ new SolanaBalanceTool(solanaKit), @@ -616,5 +647,6 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) { new SolanaLendAssetTool(solanaKit), new SolanaTPSCalculatorTool(solanaKit), new SolanaStakeTool(solanaKit), + new SolanaFetchPriceTool(solanaKit), ]; } diff --git a/src/tools/fetch_price.ts b/src/tools/fetch_price.ts new file mode 100644 index 0000000..764e8e6 --- /dev/null +++ b/src/tools/fetch_price.ts @@ -0,0 +1,35 @@ +import { SolanaAgentKit } from "../index"; +import { Tool } from "langchain/tools"; + +/** + * Fetch the price of a given token in USDC using Jupiter API + * @param agent SolanaAgentKit instance + * @param tokenId The token mint address + * @returns The price of the token in USDC + */ +export async function fetchPrice( + agent: SolanaAgentKit, + tokenId: string +): Promise { + try { + const response = await fetch( + `https://api.jup.ag/price/v2?ids=${tokenId}` + ); + + if (!response.ok) { + throw new Error(`Failed to fetch price: ${response.statusText}`); + } + + const data = await response.json(); + + const price = data.data[tokenId]?.price; + + if (!price) { + throw new Error("Price data not available for the given token."); + } + + return price; + } catch (error: any) { + throw new Error(`Price fetch failed: ${error.message}`); + } +} \ No newline at end of file diff --git a/src/tools/index.ts b/src/tools/index.ts index f6ef508..dca3c04 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -9,4 +9,5 @@ export * from "./register_domain"; export * from "./launch_pumpfun_token"; export * from "./lend"; export * from "./get_tps"; -export * from './stake_with_jup'; \ No newline at end of file +export * from './stake_with_jup'; +export * from "./fetch_price"; \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index e5c591e..d6d4264 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -54,3 +54,11 @@ export interface LuloAccountDetailsResponse { minimumRate: string; }; } + +export interface FetchPriceResponse { + status: "success" | "error"; + tokenId?: string; + priceInUSDC?: string; + message?: string; + code?: string; +}