mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-05-16 15:10:26 +00:00
Merging
This commit is contained in:
@@ -9,9 +9,13 @@ import {
|
||||
transfer,
|
||||
trade,
|
||||
registerDomain,
|
||||
resolveSolDomain,
|
||||
getPrimaryDomain,
|
||||
launchPumpFunToken,
|
||||
lendAsset,
|
||||
getTPS,
|
||||
getTokenDataByAddress,
|
||||
getTokenDataByTicker,
|
||||
stakeWithJup,
|
||||
} from "../tools";
|
||||
import { CollectionOptions, PumpFunTokenOptions } from "../types";
|
||||
@@ -35,7 +39,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));
|
||||
@@ -69,7 +73,7 @@ export class SolanaAgentKit {
|
||||
async mintNFT(
|
||||
collectionMint: PublicKey,
|
||||
metadata: Parameters<typeof mintCollectionNFT>[2],
|
||||
recipient?: PublicKey,
|
||||
recipient?: PublicKey
|
||||
) {
|
||||
return mintCollectionNFT(this, collectionMint, metadata, recipient);
|
||||
}
|
||||
@@ -82,11 +86,19 @@ export class SolanaAgentKit {
|
||||
return registerDomain(this, name, spaceKB);
|
||||
}
|
||||
|
||||
async resolveSolDomain(domain: string) {
|
||||
return resolveSolDomain(this, domain)
|
||||
}
|
||||
|
||||
async getPrimaryDomain(account: PublicKey) {
|
||||
return getPrimaryDomain(this, account)
|
||||
}
|
||||
|
||||
async trade(
|
||||
outputMint: PublicKey,
|
||||
inputAmount: number,
|
||||
inputMint?: PublicKey,
|
||||
slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS,
|
||||
slippageBps: number = DEFAULT_OPTIONS.SLIPPAGE_BPS
|
||||
) {
|
||||
return trade(this, outputMint, inputAmount, inputMint, slippageBps);
|
||||
}
|
||||
@@ -99,12 +111,20 @@ export class SolanaAgentKit {
|
||||
return getTPS(this);
|
||||
}
|
||||
|
||||
async getTokenDataByAddress(mint: string) {
|
||||
return getTokenDataByAddress(new PublicKey(mint));
|
||||
}
|
||||
|
||||
async getTokenDataByTicker(ticker: string) {
|
||||
return getTokenDataByTicker(ticker);
|
||||
}
|
||||
|
||||
async launchPumpFunToken(
|
||||
tokenName: string,
|
||||
tokenTicker: string,
|
||||
description: string,
|
||||
imageUrl: string,
|
||||
options?: PumpFunTokenOptions,
|
||||
options?: PumpFunTokenOptions
|
||||
) {
|
||||
return launchPumpFunToken(
|
||||
this,
|
||||
@@ -112,10 +132,10 @@ export class SolanaAgentKit {
|
||||
tokenTicker,
|
||||
description,
|
||||
imageUrl,
|
||||
options,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
async stake(
|
||||
amount: number,
|
||||
) {
|
||||
|
||||
@@ -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({
|
||||
@@ -370,7 +372,7 @@ export class SolanaRegisterDomainTool extends Tool {
|
||||
|
||||
const tx = await this.solanaKit.registerDomain(
|
||||
parsedInput.name,
|
||||
parsedInput.spaceKB || 1
|
||||
parsedInput.spaceKB || 1,
|
||||
);
|
||||
|
||||
return JSON.stringify({
|
||||
@@ -390,6 +392,72 @@ export class SolanaRegisterDomainTool extends Tool {
|
||||
}
|
||||
}
|
||||
|
||||
export class SolanaResolveDomainTool extends Tool {
|
||||
name = "solana_resolve_domain";
|
||||
description = `Resolve a .sol domain to a Solana PublicKey.
|
||||
|
||||
Inputs:
|
||||
domain: string, eg "pumpfun.sol" or "pumpfun"(required)
|
||||
`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const domain = input.trim();
|
||||
const publicKey = await this.solanaKit.resolveSolDomain(domain);
|
||||
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Domain resolved successfully",
|
||||
publicKey: publicKey.toBase58(),
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class SolanaGetDomainTool extends Tool {
|
||||
name = "solana_get_domain";
|
||||
description = `Retrieve the .sol domain associated for a given account address.
|
||||
|
||||
Inputs:
|
||||
account: string, eg "4Be9CvxqHW6BYiRAxW9Q3xu1ycTMWaL5z8NX4HR3ha7t" (required)
|
||||
`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const account = new PublicKey(input.trim());
|
||||
const domain = await this.solanaKit.getPrimaryDomain(account);
|
||||
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Primary domain retrieved successfully",
|
||||
domain,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SolanaGetWalletAddressTool extends Tool {
|
||||
name = "solana_get_wallet_address";
|
||||
description = `Get the wallet address of the agent`;
|
||||
@@ -461,7 +529,7 @@ export class SolanaPumpfunTokenLaunchTool extends Tool {
|
||||
telegram: parsedInput.telegram,
|
||||
website: parsedInput.website,
|
||||
initialLiquiditySOL: parsedInput.initialLiquiditySOL,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return JSON.stringify({
|
||||
@@ -631,6 +699,68 @@ export class SolanaFetchPriceTool extends Tool {
|
||||
}
|
||||
}
|
||||
|
||||
export class SolanaTokenDataTool extends Tool {
|
||||
name = "solana_token_data";
|
||||
description = `Get the token data for a given token mint address
|
||||
|
||||
Inputs: mintAddress is required.
|
||||
mintAddress: string, eg "So11111111111111111111111111111111111111112" (required)`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const parsedInput = input.trim();
|
||||
|
||||
const tokenData = await this.solanaKit.getTokenDataByAddress(
|
||||
parsedInput
|
||||
);
|
||||
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
tokenData: tokenData,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SolanaTokenDataByTickerTool extends Tool {
|
||||
name = "solana_token_data_by_ticker";
|
||||
description = `Get the token data for a given token ticker
|
||||
|
||||
Inputs: ticker is required.
|
||||
ticker: string, eg "USDC" (required)`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const ticker = input.trim();
|
||||
const tokenData = await this.solanaKit.getTokenDataByTicker(ticker);
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
tokenData: tokenData,
|
||||
});
|
||||
} 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),
|
||||
@@ -648,5 +778,9 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
new SolanaTPSCalculatorTool(solanaKit),
|
||||
new SolanaStakeTool(solanaKit),
|
||||
new SolanaFetchPriceTool(solanaKit),
|
||||
new SolanaResolveDomainTool(solanaKit),
|
||||
new SolanaGetDomainTool(solanaKit),
|
||||
new SolanaTokenDataTool(solanaKit),
|
||||
new SolanaTokenDataByTickerTool(solanaKit),
|
||||
];
|
||||
}
|
||||
|
||||
37
src/tools/get_primary_domain.ts
Normal file
37
src/tools/get_primary_domain.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { getPrimaryDomain as _getPrimaryDomain } from "@bonfida/spl-name-service";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { SolanaAgentKit } from "../index";
|
||||
|
||||
/**
|
||||
* Retrieves the primary .sol domain associated with a given Solana public key.
|
||||
*
|
||||
* This function queries the Bonfida SPL Name Service to get the primary .sol domain for
|
||||
* a specified Solana public key. If the primary domain is stale or an error occurs during
|
||||
* the resolution, it throws an error.
|
||||
*
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param account The Solana public key for which to retrieve the primary domain
|
||||
* @returns A promise that resolves to the primary .sol domain as a string
|
||||
* @throws Error if the domain is stale or if the domain resolution fails
|
||||
*/
|
||||
export async function getPrimaryDomain(
|
||||
agent: SolanaAgentKit,
|
||||
account: PublicKey
|
||||
): Promise<string> {
|
||||
try {
|
||||
const { reverse, stale } = await _getPrimaryDomain(
|
||||
agent.connection,
|
||||
account
|
||||
);
|
||||
if (stale) {
|
||||
throw new Error(
|
||||
`Primary domain is stale for account: ${account.toBase58()}`
|
||||
);
|
||||
}
|
||||
return reverse;
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to get primary domain for account: ${account.toBase58()}`
|
||||
);
|
||||
}
|
||||
}
|
||||
70
src/tools/get_token_data.ts
Normal file
70
src/tools/get_token_data.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { JupiterTokenData } from "../types";
|
||||
|
||||
export async function getTokenDataByAddress(
|
||||
mint: PublicKey,
|
||||
): Promise<JupiterTokenData | undefined> {
|
||||
try {
|
||||
if (!mint) {
|
||||
throw new Error("Mint address is required");
|
||||
}
|
||||
|
||||
const response = await fetch("https://tokens.jup.ag/tokens?tags=verified", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const data = (await response.json()) as JupiterTokenData[];
|
||||
const token = data.find((token: JupiterTokenData) => {
|
||||
return token.address === mint.toBase58();
|
||||
});
|
||||
return token;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Error fetching token data: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTokenAddressFromTicker(
|
||||
ticker: string
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://api.dexscreener.com/latest/dex/search?q=${ticker}`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.pairs || data.pairs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Filter for Solana pairs only and sort by FDV
|
||||
let solanaPairs = data.pairs
|
||||
.filter((pair: any) => pair.chainId === "solana")
|
||||
.sort((a: any, b: any) => (b.fdv || 0) - (a.fdv || 0));
|
||||
|
||||
console.log("solanaPairs", solanaPairs);
|
||||
|
||||
solanaPairs = solanaPairs.filter(
|
||||
(pair: any) =>
|
||||
pair.baseToken.symbol.toLowerCase() === ticker.toLowerCase()
|
||||
);
|
||||
|
||||
// Return the address of the highest FDV Solana pair
|
||||
return solanaPairs[0].baseToken.address;
|
||||
} catch (error) {
|
||||
console.error("Error fetching token address from DexScreener:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTokenDataByTicker(
|
||||
ticker: string
|
||||
): Promise<JupiterTokenData | undefined> {
|
||||
const address = await getTokenAddressFromTicker(ticker);
|
||||
if (!address) {
|
||||
throw new Error(`Token address not found for ticker: ${ticker}`);
|
||||
}
|
||||
return getTokenDataByAddress(new PublicKey(address));
|
||||
}
|
||||
@@ -6,8 +6,11 @@ export * from "./mint_nft";
|
||||
export * from "./transfer";
|
||||
export * from "./trade";
|
||||
export * from "./register_domain";
|
||||
export * from "./resolve_sol_domain";
|
||||
export * from "./get_primary_domain";
|
||||
export * from "./launch_pumpfun_token";
|
||||
export * from "./lend";
|
||||
export * from "./get_tps";
|
||||
export * from "./get_token_data";
|
||||
export * from './stake_with_jup';
|
||||
export * from "./fetch_price";
|
||||
export * from "./fetch_price";
|
||||
|
||||
30
src/tools/resolve_sol_domain.ts
Normal file
30
src/tools/resolve_sol_domain.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { resolve } from "@bonfida/spl-name-service";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { SolanaAgentKit } from "../index";
|
||||
|
||||
/**
|
||||
* Resolves a .sol domain to a Solana PublicKey.
|
||||
*
|
||||
* This function uses the Bonfida SPL Name Service to resolve a given .sol domain
|
||||
* to the corresponding Solana PublicKey. The domain can be provided with or without
|
||||
* the .sol suffix.
|
||||
*
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param domain The .sol domain to resolve. This can be provided with or without the .sol TLD suffix
|
||||
* @returns A promise that resolves to the corresponding Solana PublicKey
|
||||
* @throws Error if the domain resolution fails
|
||||
*/
|
||||
export async function resolveSolDomain(
|
||||
agent: SolanaAgentKit,
|
||||
domain: string
|
||||
): Promise<PublicKey> {
|
||||
if (!domain || typeof domain !== "string") {
|
||||
throw new Error("Invalid domain. Expected a non-empty string.");
|
||||
}
|
||||
|
||||
try {
|
||||
return await resolve(agent.connection, domain);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to resolve domain: ${domain}`);
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,6 @@ export interface PumpfunLaunchResponse {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lulo Account Details response format
|
||||
*/
|
||||
@@ -55,6 +54,22 @@ export interface LuloAccountDetailsResponse {
|
||||
};
|
||||
}
|
||||
|
||||
export interface JupiterTokenData {
|
||||
address: string;
|
||||
name: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
tags: string[];
|
||||
logoURI: string;
|
||||
daily_volume: number;
|
||||
freeze_authority: string | null;
|
||||
mint_authority: string | null;
|
||||
permanent_delegate: string | null;
|
||||
extensions: {
|
||||
coingeckoId?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface FetchPriceResponse {
|
||||
status: "success" | "error";
|
||||
tokenId?: string;
|
||||
|
||||
Reference in New Issue
Block a user