From 91f7b8a4787d8e784876e08c04a037bdec2fa13e Mon Sep 17 00:00:00 2001 From: Arihant Bansal <17180950+arihantbansal@users.noreply.github.com> Date: Thu, 12 Dec 2024 01:26:12 +0530 Subject: [PATCH 1/6] feat: add staking --- README.md | 15 ++++++++ src/agent/index.ts | 7 ++++ src/langchain/index.ts | 71 ++++++++++++++++++++++++++++++------- src/tools/index.ts | 1 + src/tools/stake_with_jup.ts | 39 ++++++++++++++++++++ 5 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 src/tools/stake_with_jup.ts diff --git a/README.md b/README.md index 2dd01d8..d098bf6 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ A powerful toolkit for interacting with the Solana blockchain, providing easy-to - Deploy new SPL tokens - Transfer SOL and SPL tokens - Check token balances + - Stake SOL - 🖼️ NFT Management - Deploy NFT collections @@ -110,6 +111,17 @@ const signature = await lendAsset( ); ``` +### Stake SOL + +```typescript +import { stakeWithJup } from 'solana-agent-kit'; + +const signature = await stakeWithJup( + agent, + 1 // amount in SOL +); +``` + ## API Reference ### Core Functions @@ -135,6 +147,9 @@ Check SOL or token balance for the agent's wallet. #### `lendAsset(agent, assetMint, amount, apiKey)` Lend idle assets to earn interest with Lulo. +#### `stakeWithJup(agent, amount)` +Stake SOL with Jupiter to earn rewards. + ## Dependencies The toolkit relies on several key Solana and Metaplex libraries: diff --git a/src/agent/index.ts b/src/agent/index.ts index 483763d..b7c0ade 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -10,6 +10,7 @@ import { trade, registerDomain, launchPumpFunToken, + stakeWithJup, } from "../tools"; import { CollectionOptions, PumpFunTokenOptions } from "../types"; import { DEFAULT_OPTIONS } from "../constants"; @@ -101,4 +102,10 @@ export class SolanaAgentKit { options ); } + + async stake( + amount: number, + ) { + return stakeWithJup(this, amount); + } } diff --git a/src/langchain/index.ts b/src/langchain/index.ts index da063c1..4f1f876 100644 --- a/src/langchain/index.ts +++ b/src/langchain/index.ts @@ -42,7 +42,7 @@ export class SolanaTransferTool extends Tool { name = "solana_transfer"; description = `Transfer tokens or SOL to another address ( also called as wallet address ). - Inputs ( input is a JSON string ): + Inputs ( input is a JSON string ): to: string, eg "8x2dR8Mpzuz2YqyZyZjUbYWKSWesBo5jMx2Q9Y86udVk" (required) amount: number, eg 1 (required) mint?: string, eg "So11111111111111111111111111111111111111112" or "SENDdRQtYMWaQrBroBrJ2Q53fgVuq95CV9UPGEvpCxa" (optional)`; @@ -64,7 +64,7 @@ export class SolanaTransferTool extends Tool { const tx = await this.solanaKit.transfer( recipient, parsedInput.amount, - mintAddress + mintAddress, ); return JSON.stringify({ @@ -102,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 ( @@ -159,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) { @@ -169,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 ( @@ -178,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`, ); } }); @@ -246,7 +246,9 @@ 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({ @@ -290,7 +292,7 @@ export class SolanaTradeTool extends Tool { parsedInput.inputMint ? new PublicKey(parsedInput.inputMint) : new PublicKey("So11111111111111111111111111111111111111112"), - parsedInput.slippageBps + parsedInput.slippageBps, ); return JSON.stringify({ @@ -371,7 +373,7 @@ export class SolanaRegisterDomainTool extends Tool { const tx = await this.solanaKit.registerDomain( parsedInput.name, - parsedInput.spaceKB || 1 + parsedInput.spaceKB || 1, ); return JSON.stringify({ @@ -409,9 +411,9 @@ export class SolanaPumpfunTokenLaunchTool extends Tool { description = `This tool can be used to launch a token on Pump.fun, do not use this tool for any other purpose, or for creating SPL tokens. - If the user asks you to chose the parameters, you should generate valid values. + If the user asks you to chose the parameters, you should generate valid values. For generating the image, you can use the solana_create_image tool. - + Inputs: tokenName: string, eg "PumpFun Token", tokenTicker: string, eg "PUMP", @@ -463,7 +465,7 @@ export class SolanaPumpfunTokenLaunchTool extends Tool { telegram: parsedInput.telegram, website: parsedInput.website, initialLiquiditySOL: parsedInput.initialLiquiditySOL, - } + }, ); return JSON.stringify({ @@ -517,6 +519,50 @@ export class SolanaCreateImageTool extends Tool { } } +export class SolanaStakeTool extends Tool { + name = "solana_stake"; + description = `This tool can be used to stake your SOL (Solana) + + Inputs ( input is a JSON string ): + amount: number, eg 1 or 0.01 (required)`; + + constructor(private solanaKit: SolanaAgentKit) { + super(); + } + + private validateInput(input: any): void { + if ( + input.amount !== undefined && + (typeof input.amount !== "number" || input.amount <= 0) + ) { + throw new Error("amount must be a positive number when provided"); + } + } + + protected async _call(input: string): Promise { + try { + const parsedInput = toJSON(input); + this.validateInput(parsedInput); + + const tx = await this.solanaKit.stake(parsedInput.amount); + + return JSON.stringify({ + status: "success", + message: "Staked successfully", + transaction: tx, + amount: parsedInput.amount, + }); + } catch (error: any) { + console.log(error); + return JSON.stringify({ + status: "error", + message: error.message, + code: error.code || "UNKNOWN_ERROR", + }); + } + } +} + export function createSolanaTools(solanaKit: SolanaAgentKit) { return [ new SolanaBalanceTool(solanaKit), @@ -530,5 +576,6 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) { new SolanaGetWalletAddressTool(solanaKit), new SolanaPumpfunTokenLaunchTool(solanaKit), new SolanaCreateImageTool(solanaKit), + new SolanaStakeTool(solanaKit), ]; } diff --git a/src/tools/index.ts b/src/tools/index.ts index b559ab4..5eb38ca 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -7,3 +7,4 @@ export * from './transfer'; export * from './trade'; export * from './register_domain'; export * from './launch_pumpfun_token'; +export * from './stake_with_jup'; \ No newline at end of file diff --git a/src/tools/stake_with_jup.ts b/src/tools/stake_with_jup.ts new file mode 100644 index 0000000..17c153c --- /dev/null +++ b/src/tools/stake_with_jup.ts @@ -0,0 +1,39 @@ +import { VersionedTransaction } from "@solana/web3.js"; +import { SolanaAgentKit } from "../agent"; + +/** + * Stake SOL with Jup validator + * @param agent SolanaAgentKit instance + * @param amount Amount of SOL to stake + * @returns Transaction signature + */ +export async function stakeWithJup( + agent: SolanaAgentKit, + amount: number, +): Promise { + try { + const res = await fetch( + `https://worker.jup.ag/blinks/swap/So11111111111111111111111111111111111111112/jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v/${amount}`, + { + method: "POST", + body: JSON.stringify({ + account: agent.wallet.publicKey.toBase58(), + }), + }, + ); + + const data = await res.json(); + + const txn = VersionedTransaction.deserialize( + Buffer.from(data.transaction, "base64"), + ); + + // Sign and send transaction + txn.sign([agent.wallet]); + const signature = await agent.connection.sendTransaction(txn); + return signature; + } catch (error: any) { + console.error(error); + throw new Error(`jupSOL staking failed: ${error.message}`); + } +} From 0ba572f18420f8994083e5e41569d06104eb4c40 Mon Sep 17 00:00:00 2001 From: Arihant Bansal <17180950+arihantbansal@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:37:29 +0530 Subject: [PATCH 2/6] fix --- src/tools/stake_with_jup.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/tools/stake_with_jup.ts b/src/tools/stake_with_jup.ts index 17c153c..e152532 100644 --- a/src/tools/stake_with_jup.ts +++ b/src/tools/stake_with_jup.ts @@ -16,6 +16,9 @@ export async function stakeWithJup( `https://worker.jup.ag/blinks/swap/So11111111111111111111111111111111111111112/jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v/${amount}`, { method: "POST", + headers: { + "Content-Type": "application/json", + }, body: JSON.stringify({ account: agent.wallet.publicKey.toBase58(), }), @@ -28,9 +31,23 @@ export async function stakeWithJup( Buffer.from(data.transaction, "base64"), ); + const { blockhash } = await agent.connection.getLatestBlockhash(); + txn.message.recentBlockhash = blockhash; + // Sign and send transaction txn.sign([agent.wallet]); - const signature = await agent.connection.sendTransaction(txn); + const signature = await agent.connection.sendTransaction(txn, { + preflightCommitment: "confirmed", + maxRetries: 3, + }); + + const latestBlockhash = await agent.connection.getLatestBlockhash(); + await agent.connection.confirmTransaction({ + signature, + blockhash: latestBlockhash.blockhash, + lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, + }); + return signature; } catch (error: any) { console.error(error); From 751738f7dec23cc960dced95188616ed7e2ec0b9 Mon Sep 17 00:00:00 2001 From: aryan Date: Mon, 16 Dec 2024 02:22:02 +0530 Subject: [PATCH 3/6] fix: jup staking --- src/langchain/index.ts | 18 ++---------------- src/tools/deploy_token.ts | 11 ----------- src/tools/launch_pumpfun_token.ts | 18 ------------------ src/tools/trade.ts | 2 -- 4 files changed, 2 insertions(+), 47 deletions(-) diff --git a/src/langchain/index.ts b/src/langchain/index.ts index 4f1f876..a406c61 100644 --- a/src/langchain/index.ts +++ b/src/langchain/index.ts @@ -54,7 +54,6 @@ export class SolanaTransferTool extends Tool { protected async _call(input: string): Promise { try { const parsedInput = JSON.parse(input); - console.log(parsedInput); const recipient = new PublicKey(parsedInput.to); const mintAddress = parsedInput.mint @@ -304,7 +303,6 @@ export class SolanaTradeTool extends Tool { outputToken: parsedInput.outputMint, }); } catch (error: any) { - console.log(error); return JSON.stringify({ status: "error", message: error.message, @@ -425,7 +423,6 @@ export class SolanaPumpfunTokenLaunchTool extends Tool { } private validateInput(input: any): void { - console.log(input); if (!input.tokenName || typeof input.tokenName !== "string") { throw new Error("tokenName is required and must be a string"); } @@ -521,7 +518,7 @@ export class SolanaCreateImageTool extends Tool { export class SolanaStakeTool extends Tool { name = "solana_stake"; - description = `This tool can be used to stake your SOL (Solana) + description = `This tool can be used to stake your SOL (Solana), also called as SOL staking or liquid staking. Inputs ( input is a JSON string ): amount: number, eg 1 or 0.01 (required)`; @@ -530,19 +527,9 @@ export class SolanaStakeTool extends Tool { super(); } - private validateInput(input: any): void { - if ( - input.amount !== undefined && - (typeof input.amount !== "number" || input.amount <= 0) - ) { - throw new Error("amount must be a positive number when provided"); - } - } - protected async _call(input: string): Promise { try { - const parsedInput = toJSON(input); - this.validateInput(parsedInput); + const parsedInput = JSON.parse(input) || Number(input); const tx = await this.solanaKit.stake(parsedInput.amount); @@ -553,7 +540,6 @@ export class SolanaStakeTool extends Tool { amount: parsedInput.amount, }); } catch (error: any) { - console.log(error); return JSON.stringify({ status: "error", message: error.message, diff --git a/src/tools/deploy_token.ts b/src/tools/deploy_token.ts index 65d537a..4b0b497 100644 --- a/src/tools/deploy_token.ts +++ b/src/tools/deploy_token.ts @@ -27,10 +27,6 @@ export async function deploy_token( ); const mint = Keypair.generate(); - - console.log("Mint address: ", mint.publicKey.toString()); - console.log("Agent address: ", agent.wallet_address.toString()); - let account_create_ix = SystemProgram.createAccount({ fromPubkey: agent.wallet_address, newAccountPubkey: mint.publicKey, @@ -51,13 +47,6 @@ export async function deploy_token( let hash = await sendTx(agent, tx, [mint]); - console.log("Transaction hash: ", hash); - - console.log( - "Token deployed successfully. Mint address: ", - mint.publicKey.toString() - ); - return { mint: mint.publicKey, }; diff --git a/src/tools/launch_pumpfun_token.ts b/src/tools/launch_pumpfun_token.ts index 42c9ee0..397a177 100644 --- a/src/tools/launch_pumpfun_token.ts +++ b/src/tools/launch_pumpfun_token.ts @@ -38,7 +38,6 @@ async function uploadMetadata( finalFormData.append('file', files.file); } - console.log("Final form data:", finalFormData); const metadataResponse = await fetch("https://pump.fun/api/ipfs", { method: "POST", @@ -46,7 +45,6 @@ async function uploadMetadata( }); if (!metadataResponse.ok) { - console.log("Metadata response:", await metadataResponse.json()); throw new Error(`Metadata upload failed: ${metadataResponse.statusText}`); } @@ -152,30 +150,14 @@ export async function launchPumpFunToken( options?: PumpFunTokenOptions ) { try { - // TBD : Remove clgs after approval - console.log("Starting token launch process..."); - // Generate mint keypair const mintKeypair = Keypair.generate(); - console.log("Mint public key:", mintKeypair.publicKey.toBase58()); - - // Upload metadata - console.log("Uploading metadata to IPFS..."); const metadataResponse = await uploadMetadata(tokenName, tokenTicker, description, imageUrl, options); - console.log("Metadata response:", metadataResponse); - - // Create token transaction - console.log("Creating token transaction..."); const response = await createTokenTransaction(agent, mintKeypair, metadataResponse, options); - const transactionData = await response.arrayBuffer(); const tx = VersionedTransaction.deserialize(new Uint8Array(transactionData)); - - // Send transaction with proper blockhash handling - console.log("Sending transaction..."); const signature = await signAndSendTransaction(agent, tx, mintKeypair); - console.log("Token launch successful!"); return { signature, mint: mintKeypair.publicKey.toBase58(), diff --git a/src/tools/trade.ts b/src/tools/trade.ts index d31055d..b17bc41 100644 --- a/src/tools/trade.ts +++ b/src/tools/trade.ts @@ -19,8 +19,6 @@ export async function trade( slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS, ): Promise { try { - // Get quote for the swap - console.log(inputMint.toString(), outputMint.toString(), inputAmount, slippageBps); const quoteResponse = await ( await fetch( `${JUP_API}/quote?` + From 41d6045132e1bbdf1a14fbcfa8f7b81c10ae9ac0 Mon Sep 17 00:00:00 2001 From: aryan Date: Mon, 16 Dec 2024 02:33:29 +0530 Subject: [PATCH 4/6] fix: pkg version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 385d3e6..47db16c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "solana-agent-kit", - "version": "1.1.0", + "version": "1.1.1", "description": "A toolkit for interacting with the Solana blockchain using LangChain", "main": "dist/index.js", "types": "dist/index.d.ts", From fc0165f5c25436902f70473de50fb05be46d4def Mon Sep 17 00:00:00 2001 From: aryan Date: Mon, 16 Dec 2024 02:42:05 +0530 Subject: [PATCH 5/6] feat: price --- README.md | 13 ++++++++++ src/langchain/index.ts | 54 ++++++++++++++++++++++++++++++++-------- src/tools/fetch_price.ts | 35 ++++++++++++++++++++++++++ src/tools/index.ts | 3 ++- src/types/index.ts | 8 ++++++ 5 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 src/tools/fetch_price.ts 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; +} From 518e005596b9f4fa7713dc03cc1912d6c1baadb9 Mon Sep 17 00:00:00 2001 From: aryan Date: Mon, 16 Dec 2024 02:49:11 +0530 Subject: [PATCH 6/6] chore --- .env.example | 3 + CONTRIBUTING.md | 154 ++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE.md | 21 +++++++ 3 files changed, 178 insertions(+) create mode 100644 .env.example create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e2a6d1a --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +OPENAI_API_KEY= +HELIUS_API_KEY= +SOLANA_PRIVATE_KEY= \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6b14ea8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,154 @@ +# Contributing to Solana Agent Kit + +First off, thank you for considering contributing to Solana Agent Kit! 🎉 Your contributions are **greatly appreciated**. + +## Table of Contents + +- [Contributing to Solana Agent Kit](#contributing-to-solana-agent-kit) + - [Table of Contents](#table-of-contents) + - [Code of Conduct](#code-of-conduct) + - [How Can I Contribute?](#how-can-i-contribute) + - [Reporting Bugs](#reporting-bugs) + - [Suggesting Enhancements](#suggesting-enhancements) + - [Your First Code Contribution](#your-first-code-contribution) + - [Pull Requests](#pull-requests) + - [Style Guides](#style-guides) + - [Code Style](#code-style) + - [Commit Messages](#commit-messages) + - [Naming Conventions](#naming-conventions) + - [Development Setup](#development-setup) + - [Prerequisites](#prerequisites) + - [Installation](#installation) + - [Building the Project](#building-the-project) + - [Running Tests](#running-tests) + - [Generating Documentation](#generating-documentation) + - [Security](#security) + - [License](#license) + +## Code of Conduct + +This project adheres to the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/). By participating, you are expected to uphold this code. Please report unacceptable behavior to [aryan@sendai.fun](mailto:aryan@sendai.fun). + +## How Can I Contribute? + +### Reporting Bugs + +**Great**! Opening an issue is the best way to help us improve. Here's how you can report a bug: + +1. **Search** the [existing issues](https://github.com/sendaifun/solana-agent-kit/issues) to make sure it hasn't been reported. +2. **Open a new issue** and fill out the template with as much information as possible. +3. **Provide reproduction steps** if applicable. + +### Suggesting Enhancements + +We welcome your ideas for improving Solana Agent Kit! To suggest an enhancement: + +1. **Search** the [existing issues](https://github.com/sendaifun/solana-agent-kit/issues) to see if it's already been suggested. +2. **Open a new issue** and describe your idea in detail. + +### Your First Code Contribution + +Unsure where to start? You can help out by: + +- Fixing simple bugs. +- Improving documentation. +- Adding tests. + +Check out the [Good First Issues](https://github.com/sendaifun/solana-agent-kit/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to get started! + +### Pull Requests + +1. **Fork** the repository. +2. **Create** a new branch for your feature or bugfix. + ```bash + git checkout -b feature/your-feature-name + ``` +3. **Commit** your changes with clear and descriptive messages. +4. **Push** to your fork. + ```bash + git push origin feature/your-feature-name + ``` +5. **Open a Pull Request** against the `main` branch of this repository. + +## Style Guides + +### Code Style + +- **Language**: TypeScript +- **Formatting**: Follow the existing codebase formatting. Consider using [Prettier](https://prettier.io/) for consistent code formatting. +- **Linting**: Adhere to the linting rules defined in `.eslintrc`. Ensure all linting checks pass before submitting a PR. + +### Commit Messages + +Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for your commit messages. Examples: + +- `feat: add ability to deploy new SPL token` +- `fix: handle edge case when deploying collection` +- `docs: update README with new usage examples` + +### Naming Conventions + +- **Variables and Functions**: `camelCase` +- **Classes and Types**: `PascalCase` +- **Constants**: `UPPER_SNAKE_CASE` + +## Development Setup + +### Prerequisites + +- **Node.js**: v23.x or higher +- **npm**: v10.x or higher +- **Git**: Installed and configured + +### Installation + +1. **Clone** the repository: + ```bash + git clone https://github.com/yourusername/solana-agent-kit.git + ``` +2. **Navigate** to the project directory: + ```bash + cd solana-agent-kit + ``` +3. **Install** dependencies: + ```bash + pnpm install + ``` + +### Building the Project + +To compile the TypeScript code: + +```bash +pnpm run build +``` + +### Running Tests + +To execute the test suite: + +```bash +pnpm run test +``` + +### Generating Documentation + +To generate the project documentation using TypeDoc: + +```bash +npm run docs +``` + +The documentation will be available in the `docs/` directory. + +## Security + +This toolkit handles sensitive information such as private keys and API keys. **Ensure you never commit `.env` files or any sensitive data**. Review the `.gitignore` to confirm that sensitive files are excluded. + +For security vulnerabilities, please follow the [responsible disclosure](mailto:aryan@sendai.fun) process. + +## License + +This project is licensed under the [ISC License](LICENSE). + +--- diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..e887a9d --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 SendAI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.