Merge branch 'main' into calintje/main

This commit is contained in:
aryan
2024-12-20 19:16:08 +05:30
37 changed files with 1798 additions and 568 deletions

View File

@@ -90,38 +90,30 @@ export class SolanaTransferTool extends Tool {
export class SolanaDeployTokenTool extends Tool {
name = "solana_deploy_token";
description =
"Deploy a new SPL token. Input should be JSON string with: {decimals?: number, initialSupply?: number}";
description = `Deploy a new token on Solana blockchain.
Inputs (input is a JSON string):
name: string, eg "My Token" (required)
uri: string, eg "https://example.com/token.json" (required)
symbol: string, eg "MTK" (required)
decimals?: number, eg 9 (optional, defaults to 9)
initialSupply?: number, eg 1000000 (optional)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
private validateInput(input: any): void {
if (
input.decimals !== undefined &&
(typeof input.decimals !== "number" ||
input.decimals < 0 ||
input.decimals > 9)
) {
throw new Error(
"decimals must be a number between 0 and 9 when provided"
);
}
if (
input.initialSupply !== undefined &&
(typeof input.initialSupply !== "number" || input.initialSupply <= 0)
) {
throw new Error("initialSupply must be a positive number when provided");
}
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = toJSON(input);
this.validateInput(parsedInput);
const parsedInput = JSON.parse(input);
const result = await this.solanaKit.deployToken(parsedInput.decimals);
const result = await this.solanaKit.deployToken(
parsedInput.name,
parsedInput.uri,
parsedInput.symbol,
parsedInput.decimals,
parsedInput.initialSupply
);
return JSON.stringify({
status: "success",
@@ -141,57 +133,20 @@ export class SolanaDeployTokenTool extends Tool {
export class SolanaDeployCollectionTool extends Tool {
name = "solana_deploy_collection";
description =
"Deploy a new NFT collection. Input should be JSON with: {name: string, uri: string, royaltyBasisPoints?: number, creators?: Array<{address: string, percentage: number}>}";
description = `Deploy a new NFT collection on Solana blockchain.
Inputs (input is a JSON string):
name: string, eg "My Collection" (required)
uri: string, eg "https://example.com/collection.json" (required)
royaltyBasisPoints?: number, eg 500 for 5% (optional)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
private validateInput(input: any): void {
if (!input.name || typeof input.name !== "string") {
throw new Error("name is required and must be a string");
}
if (!input.uri || typeof input.uri !== "string") {
throw new Error("uri is required and must be a string");
}
if (
input.royaltyBasisPoints !== undefined &&
(typeof input.royaltyBasisPoints !== "number" ||
input.royaltyBasisPoints < 0 ||
input.royaltyBasisPoints > 10000)
) {
throw new Error(
"royaltyBasisPoints must be a number between 0 and 10000 when provided"
);
}
if (input.creators) {
if (!Array.isArray(input.creators)) {
throw new Error("creators must be an array when provided");
}
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`
);
}
if (
typeof creator.percentage !== "number" ||
creator.percentage < 0 ||
creator.percentage > 100
) {
throw new Error(
`creator[${index}].percentage must be a number between 0 and 100`
);
}
});
}
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = toJSON(input);
this.validateInput(parsedInput);
const parsedInput = JSON.parse(input);
const result = await this.solanaKit.deployCollection(parsedInput);
@@ -213,50 +168,42 @@ export class SolanaDeployCollectionTool extends Tool {
export class SolanaMintNFTTool extends Tool {
name = "solana_mint_nft";
description =
"Mint a new NFT in a collection. Input should be JSON with: {collectionMint: string, metadata: {name: string, symbol: string, uri: string}, recipient?: string}";
description = `Mint a new NFT in a collection on Solana blockchain.
Inputs (input is a JSON string):
collectionMint: string, eg "J1S9H3QjnRtBbbuD4HjPV6RpRhwuk4zKbxsnCHuTgh9w" (required) - The address of the collection to mint into
name: string, eg "My NFT" (required)
uri: string, eg "https://example.com/nft.json" (required)
recipient?: string, eg "9aUn5swQzUTRanaaTwmszxiv89cvFwUCjEBv1vZCoT1u" (optional) - The wallet to receive the NFT, defaults to agent's wallet which is ${this.solanaKit.wallet_address.toString()}`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
private validateInput(input: any): void {
if (!input.collectionMint || typeof input.collectionMint !== "string") {
throw new Error("collectionMint is required and must be a string");
}
if (!input.metadata || typeof input.metadata !== "object") {
throw new Error("metadata is required and must be an object");
}
if (!input.metadata.name || typeof input.metadata.name !== "string") {
throw new Error("metadata.name is required and must be a string");
}
if (!input.metadata.symbol || typeof input.metadata.symbol !== "string") {
throw new Error("metadata.symbol is required and must be a string");
}
if (!input.metadata.uri || typeof input.metadata.uri !== "string") {
throw new Error("metadata.uri is required and must be a string");
}
if (input.recipient !== undefined && typeof input.recipient !== "string") {
throw new Error("recipient must be a string when provided");
}
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = toJSON(input);
this.validateInput(parsedInput);
const parsedInput = JSON.parse(input);
const result = await this.solanaKit.mintNFT(
new PublicKey(parsedInput.collectionMint),
parsedInput.metadata,
parsedInput.recipient ? new PublicKey(parsedInput.recipient) : undefined
{
name: parsedInput.name,
uri: parsedInput.uri,
},
parsedInput.recipient
? new PublicKey(parsedInput.recipient)
: this.solanaKit.wallet_address
);
return JSON.stringify({
status: "success",
message: "NFT minted successfully",
mintAddress: result.mint.toString(),
name: parsedInput.metadata.name,
metadata: {
name: parsedInput.name,
symbol: parsedInput.symbol,
uri: parsedInput.uri,
},
recipient: parsedInput.recipient || result.mint.toString(),
});
} catch (error: any) {
@@ -393,6 +340,70 @@ 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`;
@@ -634,6 +645,110 @@ 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 class SolanaCompressedAirdropTool extends Tool {
name = "solana_compressed_airdrop";
description = `Airdrop SPL tokens with ZK Compression (also called as airdropping tokens)
Inputs (input is a JSON string):
mintAddress: string, the mint address of the token, e.g., "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN" (required)
amount: number, the amount of tokens to airdrop per recipient, e.g., 42 (required)
decimals: number, the decimals of the token, e.g., 6 (required)
recipients: string[], the recipient addresses, e.g., ["1nc1nerator11111111111111111111111111111111"] (required)
priorityFeeInLamports: number, the priority fee in lamports. Default is 30_000. (optional)
shouldLog: boolean, whether to log progress to stdout. Default is false. (optional)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
const txs = await this.solanaKit.sendCompressedAirdrop(
parsedInput.mintAddress,
parsedInput.amount,
parsedInput.decimals,
parsedInput.recipients,
parsedInput.priorityFeeInLamports || 30_000,
parsedInput.shouldLog || false
);
return JSON.stringify({
status: "success",
message: `Airdropped ${parsedInput.amount} tokens to ${parsedInput.recipients.length} recipients.`,
transactionHashes: txs,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class SolanaCreateSingleSidedWhirlpoolTool extends Tool {
name = "create_orca_single_sided_whirlpool";
description = `Create a single-sided Whirlpool with liquidity.
@@ -706,5 +821,10 @@ 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),
new SolanaCompressedAirdropTool(solanaKit),
];
}