diff --git a/README.md b/README.md index 4d85a43..7d49bc6 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ An open-source toolkit for connecting AI agents to Solana protocols. Now, any agent, using any model can autonomously perform 15+ Solana actions: - Trade tokens -- Launch new tokens +- Launch new tokens - Lend assets - Send compressed airdrops - Execute blinks @@ -96,10 +96,10 @@ const tools = createSolanaTools(agent); ### Deploy a New Token ```typescript -import { deploy_token } from "solana-agent-kit"; - -const result = await deploy_token( - agent, +const result = await agent.deployToken( + "my ai token", // name + "uri", // uri + "token", // symbol 9, // decimals 1000000 // initial supply ); @@ -110,9 +110,7 @@ console.log("Token Mint Address:", result.mint.toString()); ### Create NFT Collection ```typescript -import { deploy_collection } from "solana-agent-kit"; - -const collection = await deploy_collection(agent, { +const collection = await agent.deployCollection({ name: "My NFT Collection", uri: "https://arweave.net/metadata.json", royaltyBasisPoints: 500, // 5% @@ -128,11 +126,9 @@ const collection = await deploy_collection(agent, { ### Swap Tokens ```typescript -import { trade } from "solana-agent-kit"; import { PublicKey } from "@solana/web3.js"; -const signature = await trade( - agent, +const signature = await agent.trade( new PublicKey("target-token-mint"), 100, // amount new PublicKey("source-token-mint"), @@ -143,46 +139,24 @@ const signature = await trade( ### Lend Tokens ```typescript -import { lendAsset } from "solana-agent-kit"; import { PublicKey } from "@solana/web3.js"; -const signature = await lendAsset( - agent, - 100 // amount +const signature = await agent.lendAssets( + 100 // amount of USDC to lend ); ``` ### Stake SOL ```typescript -import { stakeWithJup } from "solana-agent-kit"; - -const signature = await stakeWithJup( - agent, - 1 // amount in SOL +const signature = await agent.stake( + 1 // amount in SOL to stake ); ``` -### 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); -``` - ### Send an SPL Token Airdrop via ZK Compression ```typescript -import { - sendCompressedAirdrop, - getAirdropCostEstimate, -} from "solana-agent-kit"; import { PublicKey } from "@solana/web3.js"; (async () => { @@ -194,8 +168,7 @@ import { PublicKey } from "@solana/web3.js"; ) ); - const signature = await sendCompressedAirdrop( - agent, + const signature = await agent.sendCompressedAirdrop( new PublicKey("JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"), // mint 42, // amount per recipient [ diff --git a/src/agent/index.ts b/src/agent/index.ts index 6b79575..56cfe74 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -1,4 +1,4 @@ -import { Connection, Keypair, PublicKey } from "@solana/web3.js";; +import { Connection, Keypair, PublicKey } from "@solana/web3.js"; import bs58 from "bs58"; import Decimal from "decimal.js"; import { DEFAULT_OPTIONS } from "../constants"; @@ -26,9 +26,16 @@ import { sendCompressedAirdrop, createOrcaSingleSidedWhirlpool, FEE_TIERS, - pythFetchPrice + pythFetchPrice, } from "../tools"; -import { CollectionOptions, PumpFunTokenOptions } from "../types"; +import { + CollectionDeployment, + CollectionOptions, + JupiterTokenData, + MintCollectionNFTResponse, + PumpfunLaunchResponse, + PumpFunTokenOptions, +} from "../types"; import { BN } from "@coral-xyz/anchor"; /** @@ -49,7 +56,7 @@ export class SolanaAgentKit { constructor( private_key: string, rpc_url = "https://api.mainnet-beta.solana.com", - openai_api_key: string + openai_api_key: string, ) { this.connection = new Connection(rpc_url); this.wallet = Keypair.fromSecretKey(bs58.decode(private_key)); @@ -67,40 +74,46 @@ export class SolanaAgentKit { uri: string, symbol: string, decimals: number = DEFAULT_OPTIONS.TOKEN_DECIMALS, - initialSupply?: number - ) { + initialSupply?: number, + ): Promise<{ mint: PublicKey }> { return deploy_token(this, name, uri, symbol, decimals, initialSupply); } - async deployCollection(options: CollectionOptions) { + async deployCollection( + options: CollectionOptions, + ): Promise { return deploy_collection(this, options); } - async getBalance(token_address?: PublicKey) { + async getBalance(token_address?: PublicKey): Promise { return get_balance(this, token_address); } async mintNFT( collectionMint: PublicKey, metadata: Parameters[2], - recipient?: PublicKey - ) { + recipient?: PublicKey, + ): Promise { return mintCollectionNFT(this, collectionMint, metadata, recipient); } - async transfer(to: PublicKey, amount: number, mint?: PublicKey) { + async transfer( + to: PublicKey, + amount: number, + mint?: PublicKey, + ): Promise { return transfer(this, to, amount, mint); } - async registerDomain(name: string, spaceKB?: number) { + async registerDomain(name: string, spaceKB?: number): Promise { return registerDomain(this, name, spaceKB); } - async resolveSolDomain(domain: string) { + async resolveSolDomain(domain: string): Promise { return resolveSolDomain(this, domain); } - async getPrimaryDomain(account: PublicKey) { + async getPrimaryDomain(account: PublicKey): Promise { return getPrimaryDomain(this, account); } @@ -108,24 +121,28 @@ export class SolanaAgentKit { outputMint: PublicKey, inputAmount: number, inputMint?: PublicKey, - slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS - ) { + slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS, + ): Promise { return trade(this, outputMint, inputAmount, inputMint, slippageBps); } - async lendAssets(amount: number) { + async lendAssets(amount: number): Promise { return lendAsset(this, amount); } - async getTPS() { + async getTPS(): Promise { return getTPS(this); } - async getTokenDataByAddress(mint: string) { + async getTokenDataByAddress( + mint: string, + ): Promise { return getTokenDataByAddress(new PublicKey(mint)); } - async getTokenDataByTicker(ticker: string) { + async getTokenDataByTicker( + ticker: string, + ): Promise { return getTokenDataByTicker(ticker); } @@ -134,19 +151,19 @@ export class SolanaAgentKit { tokenTicker: string, description: string, imageUrl: string, - options?: PumpFunTokenOptions - ) { + options?: PumpFunTokenOptions, + ): Promise { return launchPumpFunToken( this, tokenName, tokenTicker, description, imageUrl, - options + options, ); } - async stake(amount: number) { + async stake(amount: number): Promise { return stakeWithJup(this, amount); } @@ -156,7 +173,7 @@ export class SolanaAgentKit { decimals: number, recipients: string[], priorityFeeInLamports: number, - shouldLog: boolean + shouldLog: boolean, ): Promise { return await sendCompressedAirdrop( this, @@ -165,7 +182,7 @@ export class SolanaAgentKit { decimals, recipients.map((recipient) => new PublicKey(recipient)), priorityFeeInLamports, - shouldLog + shouldLog, ); } @@ -176,7 +193,7 @@ export class SolanaAgentKit { initialPrice: Decimal, maxPrice: Decimal, feeTier: keyof typeof FEE_TIERS, - ) { + ): Promise { return createOrcaSingleSidedWhirlpool( this, depositTokenAmount, @@ -184,18 +201,16 @@ export class SolanaAgentKit { otherTokenMint, initialPrice, maxPrice, - feeTier - ) + feeTier, + ); } async raydiumCreateAmmV4( marketId: PublicKey, - baseAmount: BN, quoteAmount: BN, - startTime: BN, - ) { + ): Promise { return raydiumCreateAmmV4( this, marketId, @@ -204,64 +219,51 @@ export class SolanaAgentKit { quoteAmount, startTime, - ) + ); } async raydiumCreateClmm( mint1: PublicKey, mint2: PublicKey, - configId: PublicKey, - initialPrice: Decimal, startTime: BN, - ) { + ): Promise { return raydiumCreateClmm( this, - mint1, mint2, - configId, - initialPrice, startTime, - ) + ); } async raydiumCreateCpmm( mint1: PublicKey, mint2: PublicKey, - configId: PublicKey, - mintAAmount: BN, mintBAmount: BN, - startTime: BN, - ) { + ): Promise { return raydiumCreateCpmm( this, - mint1, mint2, - configId, - mintAAmount, mintBAmount, - startTime, - ) + ); } async openbookCreateMarket( baseMint: PublicKey, quoteMint: PublicKey, - lotSize: number = 1, tickSize: number = 0.01, - ) { + ): Promise { return openbookCreateMarket( this, baseMint, diff --git a/src/tools/get_balance.ts b/src/tools/get_balance.ts index 2bdf3f2..05a56a1 100644 --- a/src/tools/get_balance.ts +++ b/src/tools/get_balance.ts @@ -9,11 +9,15 @@ import { SolanaAgentKit } from "../index"; */ export async function get_balance( agent: SolanaAgentKit, - token_address?: PublicKey -) { + token_address?: PublicKey, +): Promise { if (!token_address) - return await agent.connection.getBalance(agent.wallet_address) / LAMPORTS_PER_SOL + return ( + (await agent.connection.getBalance(agent.wallet_address)) / + LAMPORTS_PER_SOL + ); - const token_account = await agent.connection.getTokenAccountBalance(token_address); - return token_account.value.uiAmount; + const token_account = + await agent.connection.getTokenAccountBalance(token_address); + return token_account.value.uiAmount || 0; } diff --git a/src/tools/launch_pumpfun_token.ts b/src/tools/launch_pumpfun_token.ts index 397a177..0c3e6f5 100644 --- a/src/tools/launch_pumpfun_token.ts +++ b/src/tools/launch_pumpfun_token.ts @@ -1,23 +1,27 @@ // src/tools/launch_pumpfun_token.ts import { VersionedTransaction, Keypair } from "@solana/web3.js"; -import { PumpFunTokenOptions, SolanaAgentKit } from "../index"; +import { + PumpfunLaunchResponse, + PumpFunTokenOptions, + SolanaAgentKit, +} from "../index"; async function uploadMetadata( - tokenName: string, + tokenName: string, tokenTicker: string, description: string, imageUrl: string, - options?: PumpFunTokenOptions + options?: PumpFunTokenOptions, ): Promise { // Create metadata object const formData = new URLSearchParams(); - formData.append('name', tokenName); + formData.append("name", tokenName); formData.append("symbol", tokenTicker); formData.append("description", description); formData.append("showName", "true"); - if (options?.twitter) formData.append('twitter', options.twitter); + if (options?.twitter) formData.append("twitter", options.twitter); if (options?.telegram) formData.append("telegram", options.telegram); if (options?.website) formData.append("website", options.website); @@ -35,13 +39,12 @@ async function uploadMetadata( } // Add file if exists if (files?.file) { - finalFormData.append('file', files.file); + finalFormData.append("file", files.file); } - const metadataResponse = await fetch("https://pump.fun/api/ipfs", { method: "POST", - body: finalFormData + body: finalFormData, }); if (!metadataResponse.ok) { @@ -55,7 +58,7 @@ async function createTokenTransaction( agent: SolanaAgentKit, mintKeypair: Keypair, metadataResponse: any, - options?: PumpFunTokenOptions + options?: PumpFunTokenOptions, ) { const payload = { publicKey: agent.wallet_address.toBase58(), @@ -78,12 +81,14 @@ async function createTokenTransaction( headers: { "Content-Type": "application/json", }, - body: JSON.stringify(payload) + body: JSON.stringify(payload), }); if (!response.ok) { const errorText = await response.text(); - throw new Error(`Transaction creation failed: ${response.status} - ${errorText}`); + throw new Error( + `Transaction creation failed: ${response.status} - ${errorText}`, + ); } return response; @@ -92,12 +97,13 @@ async function createTokenTransaction( async function signAndSendTransaction( kit: SolanaAgentKit, tx: VersionedTransaction, - mintKeypair: Keypair + mintKeypair: Keypair, ) { try { // Get the latest blockhash - const { blockhash, lastValidBlockHeight } = await kit.connection.getLatestBlockhash(); - + const { blockhash, lastValidBlockHeight } = + await kit.connection.getLatestBlockhash(); + // Update transaction with latest blockhash tx.message.recentBlockhash = blockhash; @@ -107,15 +113,15 @@ async function signAndSendTransaction( // Send and confirm transaction with options const signature = await kit.connection.sendTransaction(tx, { skipPreflight: false, - preflightCommitment: 'confirmed', - maxRetries: 5 + preflightCommitment: "confirmed", + maxRetries: 5, }); // Wait for confirmation const confirmation = await kit.connection.confirmTransaction({ signature, blockhash, - lastValidBlockHeight + lastValidBlockHeight, }); if (confirmation.value.err) { @@ -124,9 +130,9 @@ async function signAndSendTransaction( return signature; } catch (error) { - console.error('Transaction send error:', error); - if (error instanceof Error && 'logs' in error) { - console.error('Transaction logs:', error.logs); + console.error("Transaction send error:", error); + if (error instanceof Error && "logs" in error) { + console.error("Transaction logs:", error.logs); } throw error; } @@ -140,6 +146,7 @@ async function signAndSendTransaction( * @param description - Description of the token * @param imageUrl - URL of the token image * @param options - Optional token options (twitter, telegram, website, initialLiquiditySOL, slippageBps, priorityFee) + * @returns - Signature of the transaction, mint address and metadata URI, if successful, else error */ export async function launchPumpFunToken( agent: SolanaAgentKit, @@ -147,15 +154,27 @@ export async function launchPumpFunToken( tokenTicker: string, description: string, imageUrl: string, - options?: PumpFunTokenOptions -) { + options?: PumpFunTokenOptions, +): Promise { try { - const mintKeypair = Keypair.generate(); - const metadataResponse = await uploadMetadata(tokenName, tokenTicker, description, imageUrl, options); - const response = await createTokenTransaction(agent, mintKeypair, metadataResponse, options); + const metadataResponse = await uploadMetadata( + tokenName, + tokenTicker, + description, + imageUrl, + options, + ); + const response = await createTokenTransaction( + agent, + mintKeypair, + metadataResponse, + options, + ); const transactionData = await response.arrayBuffer(); - const tx = VersionedTransaction.deserialize(new Uint8Array(transactionData)); + const tx = VersionedTransaction.deserialize( + new Uint8Array(transactionData), + ); const signature = await signAndSendTransaction(agent, tx, mintKeypair); return { @@ -163,12 +182,11 @@ export async function launchPumpFunToken( mint: mintKeypair.publicKey.toBase58(), metadataUri: metadataResponse.metadataUri, }; - } catch (error) { console.error("Error in launchpumpfuntoken:", error); - if (error instanceof Error && 'logs' in error) { - console.error('Transaction logs:', (error as any).logs); + if (error instanceof Error && "logs" in error) { + console.error("Transaction logs:", (error as any).logs); } throw error; } -} \ No newline at end of file +}