mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-06-09 15:11:56 +00:00
Merge branch 'main' into manifest
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
OPENAI_API_KEY=
|
OPENAI_API_KEY=
|
||||||
RPC_URL=
|
RPC_URL=
|
||||||
SOLANA_PRIVATE_KEY=
|
SOLANA_PRIVATE_KEY=
|
||||||
|
JUPITER_REFERRAL_ACCOUNT=
|
||||||
|
JUPITER_FEE_BPS=
|
||||||
@@ -47,8 +47,8 @@ Anyone - whether an SF-based AI researcher or a crypto-native builder - can brin
|
|||||||
- Launch on Pump via PumpPortal
|
- Launch on Pump via PumpPortal
|
||||||
- Raydium pool creation (CPMM, CLMM, AMMv4)
|
- Raydium pool creation (CPMM, CLMM, AMMv4)
|
||||||
- Orca Whirlpool integration
|
- Orca Whirlpool integration
|
||||||
- Meteora Dynamic AMM, DLMM Pool, and Alpga Vault
|
|
||||||
- Manifest market creation, and limit orders
|
- Manifest market creation, and limit orders
|
||||||
|
- Meteora Dynamic AMM, DLMM Pool, and Alpha Vault
|
||||||
- Openbook market creation
|
- Openbook market creation
|
||||||
- Register and Resolve SNS
|
- Register and Resolve SNS
|
||||||
- Jito Bundles
|
- Jito Bundles
|
||||||
@@ -56,7 +56,7 @@ Anyone - whether an SF-based AI researcher or a crypto-native builder - can brin
|
|||||||
- Register/resolve Alldomains
|
- Register/resolve Alldomains
|
||||||
|
|
||||||
- **Solana Blinks**
|
- **Solana Blinks**
|
||||||
- Lending by Lulon (Best APR for USDC)
|
- Lending by Lulo (Best APR for USDC)
|
||||||
- Send Arcade Games
|
- Send Arcade Games
|
||||||
- JupSOL staking
|
- JupSOL staking
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ To use this feature, ensure you have the following:
|
|||||||
|
|
||||||
1. **PostgreSQL Database URL**: Create and host ur PostgreSQL databse and enter the URL. It will be of the format "postgresql://user:password@localhost:5432/db"
|
1. **PostgreSQL Database URL**: Create and host ur PostgreSQL databse and enter the URL. It will be of the format "postgresql://user:password@localhost:5432/db"
|
||||||
|
|
||||||
## Before applying persistance
|
## Without persistence
|
||||||
```
|
```
|
||||||
Available modes:
|
Available modes:
|
||||||
1. chat
|
1. chat
|
||||||
@@ -27,7 +27,7 @@ Starting chat mode... Type 'exit' to end.
|
|||||||
Prompt: i am arpit
|
Prompt: i am arpit
|
||||||
Hello Arpit! How can I assist you today?
|
Hello Arpit! How can I assist you today?
|
||||||
Prompt: ^С
|
Prompt: ^С
|
||||||
® arpitsingh Mac persistance-agent & ts-node index.ts
|
® arpitsingh Mac persistent-agent & ts-node index.ts
|
||||||
Starting Agent...
|
Starting Agent...
|
||||||
Available modes:
|
Available modes:
|
||||||
1. chat
|
1. chat
|
||||||
@@ -39,7 +39,7 @@ Starting chat mode... Type 'exit' to end.
|
|||||||
Prompt: do u know my name
|
Prompt: do u know my name
|
||||||
I don't know your name yet. If you'd like, you can share it.
|
I don't know your name yet. If you'd like, you can share it.
|
||||||
```
|
```
|
||||||
## After applying persistence
|
## With persistence
|
||||||
```
|
```
|
||||||
Available modes:
|
Available modes:
|
||||||
1. chat
|
1. chat
|
||||||
@@ -51,7 +51,7 @@ Starting chat mode... Type 'exit' to end.
|
|||||||
Prompt: i am arpit
|
Prompt: i am arpit
|
||||||
Hello Arpit! How can I assist you today?
|
Hello Arpit! How can I assist you today?
|
||||||
Prompt: ^С
|
Prompt: ^С
|
||||||
® arpitsingh Mac persistance-agent & ts-node index.ts
|
® arpitsingh Mac persistent-agent & ts-node index.ts
|
||||||
Starting Agent...
|
Starting Agent...
|
||||||
Available modes:
|
Available modes:
|
||||||
1. chat
|
1. chat
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
|
||||||
# Telegram Bot Starter with Solana Agent Kit
|
# Telegram Bot Starter with Solana Agent Kit
|
||||||
|
|
||||||
This example showcases how we can make a telegram bot with the Solana Agent Kit by Send AI.
|
This example showcases how we can make a telegram bot with the Solana Agent Kit by Send AI.
|
||||||
|
|
||||||
|
## Quick Deploy
|
||||||
|
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fsendaifun%2Fsolana-agent-kit%2Ftree%2Fmain%2Fexamples%2Ftg-bot-starter&env=OPENAI_API_KEY,RPC_URL,SOLANA_PRIVATE_KEY,TELEGRAM_BOT_TOKEN&project-name=solana-agent-kit&repository-name=sak-yourprojectname)
|
||||||
|
|
||||||
## How to get the telegram bot token
|
## How to get the telegram bot token
|
||||||
|
|
||||||
You can check [here](https://help.zoho.com/portal/en/kb/desk/support-channels/instant-messaging/telegram/articles/telegram-integration-with-zoho-desk#How_to_find_a_token_for_an_existing_Telegram_Bot) how you can obtain a bot token for your telegram bot.
|
You can check [here](https://help.zoho.com/portal/en/kb/desk/support-channels/instant-messaging/telegram/articles/telegram-integration-with-zoho-desk#How_to_find_a_token_for_an_existing_Telegram_Bot) how you can obtain a bot token for your telegram bot.
|
||||||
@@ -18,5 +20,5 @@ You can check [here](https://help.zoho.com/portal/en/kb/desk/support-channels/in
|
|||||||
- You can host it on Vercel too as we have used NextJs in this.
|
- You can host it on Vercel too as we have used NextJs in this.
|
||||||
- Once the URL is set successfully, you will see this ``` {"ok":true,"result":true,"description":"Webhook was set"} ```
|
- Once the URL is set successfully, you will see this ``` {"ok":true,"result":true,"description":"Webhook was set"} ```
|
||||||
|
|
||||||
Done!!! Congrtulations you just hosted Solana Agent Kit on a Telegram bot.
|
Done!!! Congratulations you just hosted Solana Agent Kit on a Telegram bot.
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
"@pythnetwork/price-service-client": "^1.9.0",
|
"@pythnetwork/price-service-client": "^1.9.0",
|
||||||
"@raydium-io/raydium-sdk-v2": "0.1.95-alpha",
|
"@raydium-io/raydium-sdk-v2": "0.1.95-alpha",
|
||||||
"@solana/spl-token": "^0.4.9",
|
"@solana/spl-token": "^0.4.9",
|
||||||
|
"@tensor-oss/tensorswap-sdk": "^4.5.0",
|
||||||
"@solana/web3.js": "^1.98.0",
|
"@solana/web3.js": "^1.98.0",
|
||||||
"@tiplink/api": "^0.3.1",
|
"@tiplink/api": "^0.3.1",
|
||||||
"bn.js": "^5.2.1",
|
"bn.js": "^5.2.1",
|
||||||
|
|||||||
603
pnpm-lock.yaml
generated
603
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
|||||||
import bs58 from "bs58";
|
import bs58 from "bs58";
|
||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
import { DEFAULT_OPTIONS } from "../constants";
|
import { DEFAULT_OPTIONS } from "../constants";
|
||||||
|
import { Config } from "../types";
|
||||||
import {
|
import {
|
||||||
deploy_collection,
|
deploy_collection,
|
||||||
deploy_token,
|
deploy_token,
|
||||||
@@ -47,6 +48,8 @@ import {
|
|||||||
orcaFetchPositions,
|
orcaFetchPositions,
|
||||||
rock_paper_scissor,
|
rock_paper_scissor,
|
||||||
create_TipLink,
|
create_TipLink,
|
||||||
|
listNFTForSale,
|
||||||
|
cancelListing,
|
||||||
} from "../tools";
|
} from "../tools";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -73,17 +76,17 @@ export class SolanaAgentKit {
|
|||||||
public connection: Connection;
|
public connection: Connection;
|
||||||
public wallet: Keypair;
|
public wallet: Keypair;
|
||||||
public wallet_address: PublicKey;
|
public wallet_address: PublicKey;
|
||||||
public openai_api_key: string | null;
|
public config: Config;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private_key: string,
|
private_key: string,
|
||||||
rpc_url = "https://api.mainnet-beta.solana.com",
|
rpc_url = "https://api.mainnet-beta.solana.com",
|
||||||
openai_api_key: string | null = null,
|
config: Config,
|
||||||
) {
|
) {
|
||||||
this.connection = new Connection(rpc_url);
|
this.connection = new Connection(rpc_url);
|
||||||
this.wallet = Keypair.fromSecretKey(bs58.decode(private_key));
|
this.wallet = Keypair.fromSecretKey(bs58.decode(private_key));
|
||||||
this.wallet_address = this.wallet.publicKey;
|
this.wallet_address = this.wallet.publicKey;
|
||||||
this.openai_api_key = openai_api_key;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tool methods
|
// Tool methods
|
||||||
@@ -316,8 +319,7 @@ export class SolanaAgentKit {
|
|||||||
return getOwnedDomainsForTLD(this, tld);
|
return getOwnedDomainsForTLD(this, tld);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
async getAllDomainsTLDs(): Promise<string[]> {
|
||||||
async getAllDomainsTLDs(): Promise<String[]> {
|
|
||||||
return getAllDomainsTLDs(this);
|
return getAllDomainsTLDs(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,4 +442,12 @@ export class SolanaAgentKit {
|
|||||||
async createTiplink(amount: number, splmintAddress?: PublicKey) {
|
async createTiplink(amount: number, splmintAddress?: PublicKey) {
|
||||||
return create_TipLink(this, amount, splmintAddress);
|
return create_TipLink(this, amount, splmintAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tensorListNFT(nftMint: PublicKey, price: number): Promise<string> {
|
||||||
|
return listNFTForSale(this, nftMint, price);
|
||||||
|
}
|
||||||
|
|
||||||
|
async tensorCancelListing(nftMint: PublicKey): Promise<string> {
|
||||||
|
return cancelListing(this, nftMint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,12 @@ export const TOKENS = {
|
|||||||
export const DEFAULT_OPTIONS = {
|
export const DEFAULT_OPTIONS = {
|
||||||
SLIPPAGE_BPS: 300,
|
SLIPPAGE_BPS: 300,
|
||||||
TOKEN_DECIMALS: 9,
|
TOKEN_DECIMALS: 9,
|
||||||
|
RERERRAL_FEE: 200,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jupiter API URL
|
* Jupiter API URL
|
||||||
*/
|
*/
|
||||||
export const JUP_API = "https://quote-api.jup.ag/v6";
|
export const JUP_API = "https://quote-api.jup.ag/v6";
|
||||||
|
export const JUP_REFERRAL_ADDRESS =
|
||||||
|
"REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3";
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class SolanaBalanceTool extends Tool {
|
|||||||
|
|
||||||
export class SolanaBalanceOtherTool extends Tool {
|
export class SolanaBalanceOtherTool extends Tool {
|
||||||
name = "solana_balance_other";
|
name = "solana_balance_other";
|
||||||
description = `Get the balance of a Solana wallet or token account different from the agent's wallet.
|
description = `Get the balance of a Solana wallet or token account which is different from the agent's wallet.
|
||||||
|
|
||||||
If no tokenAddress is provided, the SOL balance of the wallet will be returned.
|
If no tokenAddress is provided, the SOL balance of the wallet will be returned.
|
||||||
|
|
||||||
@@ -904,7 +904,7 @@ export class SolanaCompressedAirdropTool extends Tool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SolanaClosePostition extends Tool {
|
export class SolanaClosePosition extends Tool {
|
||||||
name = "orca_close_position";
|
name = "orca_close_position";
|
||||||
description = `Closes an existing liquidity position in an Orca Whirlpool. This function fetches the position
|
description = `Closes an existing liquidity position in an Orca Whirlpool. This function fetches the position
|
||||||
details using the provided mint address and closes the position with a 1% slippage.
|
details using the provided mint address and closes the position with a 1% slippage.
|
||||||
@@ -1186,7 +1186,7 @@ export class SolanaOrcaOpenSingleSidedPosition extends Tool {
|
|||||||
|
|
||||||
export class SolanaRaydiumCreateAmmV4 extends Tool {
|
export class SolanaRaydiumCreateAmmV4 extends Tool {
|
||||||
name = "raydium_create_ammV4";
|
name = "raydium_create_ammV4";
|
||||||
description = `Raydium's Legacy AMM that requiers an OpenBook marketID
|
description = `Raydium's Legacy AMM that requires an OpenBook marketID
|
||||||
|
|
||||||
Inputs (input is a json string):
|
Inputs (input is a json string):
|
||||||
marketId: string (required)
|
marketId: string (required)
|
||||||
@@ -1212,7 +1212,7 @@ export class SolanaRaydiumCreateAmmV4 extends Tool {
|
|||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
status: "success",
|
status: "success",
|
||||||
message: "Create raydium amm v4 pool successfully",
|
message: "Raydium amm v4 pool created successfully",
|
||||||
transaction: tx,
|
transaction: tx,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -1257,7 +1257,7 @@ export class SolanaRaydiumCreateClmm extends Tool {
|
|||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
status: "success",
|
status: "success",
|
||||||
message: "Create raydium clmm pool successfully",
|
message: "Raydium clmm pool created successfully",
|
||||||
transaction: tx,
|
transaction: tx,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -1305,7 +1305,7 @@ export class SolanaRaydiumCreateCpmm extends Tool {
|
|||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
status: "success",
|
status: "success",
|
||||||
message: "Create raydium cpmm pool successfully",
|
message: "Raydium cpmm pool created successfully",
|
||||||
transaction: tx,
|
transaction: tx,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -1347,7 +1347,7 @@ export class SolanaOpenbookCreateMarket extends Tool {
|
|||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
status: "success",
|
status: "success",
|
||||||
message: "Create openbook market successfully",
|
message: "Openbook market created successfully",
|
||||||
transaction: tx,
|
transaction: tx,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -1736,6 +1736,95 @@ export class SolanaTipLinkTool extends Tool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SolanaListNFTForSaleTool extends Tool {
|
||||||
|
name = "solana_list_nft_for_sale";
|
||||||
|
description = `List an NFT for sale on Tensor Trade.
|
||||||
|
|
||||||
|
Inputs (input is a JSON string):
|
||||||
|
nftMint: string, the mint address of the NFT (required)
|
||||||
|
price: number, price in SOL (required)`;
|
||||||
|
|
||||||
|
constructor(private solanaKit: SolanaAgentKit) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _call(input: string): Promise<string> {
|
||||||
|
try {
|
||||||
|
const parsedInput = JSON.parse(input);
|
||||||
|
|
||||||
|
// Validate NFT ownership first
|
||||||
|
const nftAccount =
|
||||||
|
await this.solanaKit.connection.getTokenAccountsByOwner(
|
||||||
|
this.solanaKit.wallet_address,
|
||||||
|
{ mint: new PublicKey(parsedInput.nftMint) },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (nftAccount.value.length === 0) {
|
||||||
|
return JSON.stringify({
|
||||||
|
status: "error",
|
||||||
|
message:
|
||||||
|
"NFT not found in wallet. Please make sure you own this NFT.",
|
||||||
|
code: "NFT_NOT_FOUND",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const tx = await this.solanaKit.tensorListNFT(
|
||||||
|
new PublicKey(parsedInput.nftMint),
|
||||||
|
parsedInput.price,
|
||||||
|
);
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
status: "success",
|
||||||
|
message: "NFT listed for sale successfully",
|
||||||
|
transaction: tx,
|
||||||
|
price: parsedInput.price,
|
||||||
|
nftMint: parsedInput.nftMint,
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
return JSON.stringify({
|
||||||
|
status: "error",
|
||||||
|
message: error.message,
|
||||||
|
code: error.code || "UNKNOWN_ERROR",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SolanaCancelNFTListingTool extends Tool {
|
||||||
|
name = "solana_cancel_nft_listing";
|
||||||
|
description = `Cancel an NFT listing on Tensor Trade.
|
||||||
|
|
||||||
|
Inputs (input is a JSON string):
|
||||||
|
nftMint: string, the mint address of the NFT (required)`;
|
||||||
|
|
||||||
|
constructor(private solanaKit: SolanaAgentKit) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _call(input: string): Promise<string> {
|
||||||
|
try {
|
||||||
|
const parsedInput = JSON.parse(input);
|
||||||
|
|
||||||
|
const tx = await this.solanaKit.tensorCancelListing(
|
||||||
|
new PublicKey(parsedInput.nftMint),
|
||||||
|
);
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
status: "success",
|
||||||
|
message: "NFT listing cancelled successfully",
|
||||||
|
transaction: tx,
|
||||||
|
nftMint: parsedInput.nftMint,
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
return JSON.stringify({
|
||||||
|
status: "error",
|
||||||
|
message: error.message,
|
||||||
|
code: error.code || "UNKNOWN_ERROR",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||||
return [
|
return [
|
||||||
new SolanaBalanceTool(solanaKit),
|
new SolanaBalanceTool(solanaKit),
|
||||||
@@ -1782,5 +1871,7 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
|||||||
new SolanaCreateGibworkTask(solanaKit),
|
new SolanaCreateGibworkTask(solanaKit),
|
||||||
new SolanaRockPaperScissorsTool(solanaKit),
|
new SolanaRockPaperScissorsTool(solanaKit),
|
||||||
new SolanaTipLinkTool(solanaKit),
|
new SolanaTipLinkTool(solanaKit),
|
||||||
|
new SolanaListNFTForSaleTool(solanaKit),
|
||||||
|
new SolanaCancelNFTListingTool(solanaKit),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ export async function create_image(
|
|||||||
n: number = 1,
|
n: number = 1,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (!agent.openai_api_key) {
|
if (!agent.config.OPENAI_API_KEY) {
|
||||||
throw new Error("OpenAI API key not found in agent configuration");
|
throw new Error("OpenAI API key not found in agent configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
const openai = new OpenAI({
|
const openai = new OpenAI({
|
||||||
apiKey: agent.openai_api_key,
|
apiKey: agent.config.OPENAI_API_KEY,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await openai.images.generate({
|
const response = await openai.images.generate({
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import { getAllTld } from "@onsol/tldparser";
|
|||||||
*/
|
*/
|
||||||
export async function getAllDomainsTLDs(
|
export async function getAllDomainsTLDs(
|
||||||
agent: SolanaAgentKit,
|
agent: SolanaAgentKit,
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
): Promise<string[]> {
|
||||||
): Promise<String[]> {
|
|
||||||
try {
|
try {
|
||||||
const tlds = await getAllTld(agent.connection);
|
const tlds = await getAllTld(agent.connection);
|
||||||
return tlds.map((tld) => tld.tld);
|
return tlds.map((tld) => String(tld.tld));
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new Error(`Failed to fetch TLDs: ${error.message}`);
|
throw new Error(`Failed to fetch TLDs: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,3 +50,5 @@ export * from "./create_gibwork_task";
|
|||||||
|
|
||||||
export * from "./rock_paper_scissor";
|
export * from "./rock_paper_scissor";
|
||||||
export * from "./create_tiplinks";
|
export * from "./create_tiplinks";
|
||||||
|
|
||||||
|
export * from "./tensor_trade";
|
||||||
|
|||||||
108
src/tools/tensor_trade.ts
Normal file
108
src/tools/tensor_trade.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { SolanaAgentKit } from "../index";
|
||||||
|
import { TensorSwapSDK } from "@tensor-oss/tensorswap-sdk";
|
||||||
|
import { PublicKey, Transaction } from "@solana/web3.js";
|
||||||
|
import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
|
||||||
|
import { BN } from "bn.js";
|
||||||
|
import {
|
||||||
|
getAssociatedTokenAddress,
|
||||||
|
TOKEN_PROGRAM_ID,
|
||||||
|
getAccount,
|
||||||
|
} from "@solana/spl-token";
|
||||||
|
|
||||||
|
export async function listNFTForSale(
|
||||||
|
agent: SolanaAgentKit,
|
||||||
|
nftMint: PublicKey,
|
||||||
|
price: number,
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
if (!PublicKey.isOnCurve(nftMint)) {
|
||||||
|
throw new Error("Invalid NFT mint address");
|
||||||
|
}
|
||||||
|
|
||||||
|
const mintInfo = await agent.connection.getAccountInfo(nftMint);
|
||||||
|
if (!mintInfo) {
|
||||||
|
throw new Error(`NFT mint ${nftMint.toString()} does not exist`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ata = await getAssociatedTokenAddress(nftMint, agent.wallet_address);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tokenAccount = await getAccount(agent.connection, ata);
|
||||||
|
|
||||||
|
if (!tokenAccount || tokenAccount.amount <= 0) {
|
||||||
|
throw new Error(`You don't own this NFT (${nftMint.toString()})`);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(
|
||||||
|
`No token account found for mint ${nftMint.toString()}. Make sure you own this NFT.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = new AnchorProvider(
|
||||||
|
agent.connection,
|
||||||
|
new Wallet(agent.wallet),
|
||||||
|
AnchorProvider.defaultOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const tensorSwapSdk = new TensorSwapSDK({ provider });
|
||||||
|
const priceInLamports = new BN(price * 1e9);
|
||||||
|
const nftSource = await getAssociatedTokenAddress(
|
||||||
|
nftMint,
|
||||||
|
agent.wallet_address,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { tx } = await tensorSwapSdk.list({
|
||||||
|
nftMint,
|
||||||
|
nftSource,
|
||||||
|
owner: agent.wallet_address,
|
||||||
|
price: priceInLamports,
|
||||||
|
tokenProgram: TOKEN_PROGRAM_ID,
|
||||||
|
payer: agent.wallet_address,
|
||||||
|
});
|
||||||
|
|
||||||
|
const transaction = new Transaction();
|
||||||
|
transaction.add(...tx.ixs);
|
||||||
|
return await agent.connection.sendTransaction(transaction, [
|
||||||
|
agent.wallet,
|
||||||
|
...tx.extraSigners,
|
||||||
|
]);
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("Full error details:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelListing(
|
||||||
|
agent: SolanaAgentKit,
|
||||||
|
nftMint: PublicKey,
|
||||||
|
): Promise<string> {
|
||||||
|
const provider = new AnchorProvider(
|
||||||
|
agent.connection,
|
||||||
|
new Wallet(agent.wallet),
|
||||||
|
AnchorProvider.defaultOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const tensorSwapSdk = new TensorSwapSDK({ provider });
|
||||||
|
const nftDest = await getAssociatedTokenAddress(
|
||||||
|
nftMint,
|
||||||
|
agent.wallet_address,
|
||||||
|
false,
|
||||||
|
TOKEN_PROGRAM_ID,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { tx } = await tensorSwapSdk.delist({
|
||||||
|
nftMint,
|
||||||
|
nftDest,
|
||||||
|
owner: agent.wallet_address,
|
||||||
|
tokenProgram: TOKEN_PROGRAM_ID,
|
||||||
|
payer: agent.wallet_address,
|
||||||
|
authData: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const transaction = new Transaction();
|
||||||
|
transaction.add(...tx.ixs);
|
||||||
|
return await agent.connection.sendTransaction(transaction, [
|
||||||
|
agent.wallet,
|
||||||
|
...tx.extraSigners,
|
||||||
|
]);
|
||||||
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
import { VersionedTransaction, PublicKey } from "@solana/web3.js";
|
import { VersionedTransaction, PublicKey } from "@solana/web3.js";
|
||||||
import { SolanaAgentKit } from "../index";
|
import { SolanaAgentKit } from "../index";
|
||||||
import { TOKENS, DEFAULT_OPTIONS, JUP_API } from "../constants";
|
import {
|
||||||
|
TOKENS,
|
||||||
|
DEFAULT_OPTIONS,
|
||||||
|
JUP_API,
|
||||||
|
JUP_REFERRAL_ADDRESS,
|
||||||
|
} from "../constants";
|
||||||
import { getMint } from "@solana/spl-token";
|
import { getMint } from "@solana/spl-token";
|
||||||
/**
|
/**
|
||||||
* Swap tokens using Jupiter Exchange
|
* Swap tokens using Jupiter Exchange
|
||||||
@@ -11,6 +16,7 @@ import { getMint } from "@solana/spl-token";
|
|||||||
* @param slippageBps Slippage tolerance in basis points (default: 300 = 3%)
|
* @param slippageBps Slippage tolerance in basis points (default: 300 = 3%)
|
||||||
* @returns Transaction signature
|
* @returns Transaction signature
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export async function trade(
|
export async function trade(
|
||||||
agent: SolanaAgentKit,
|
agent: SolanaAgentKit,
|
||||||
outputMint: PublicKey,
|
outputMint: PublicKey,
|
||||||
@@ -38,11 +44,24 @@ export async function trade(
|
|||||||
`&amount=${scaledAmount}` +
|
`&amount=${scaledAmount}` +
|
||||||
`&slippageBps=${slippageBps}` +
|
`&slippageBps=${slippageBps}` +
|
||||||
`&onlyDirectRoutes=true` +
|
`&onlyDirectRoutes=true` +
|
||||||
`&maxAccounts=20`,
|
`&maxAccounts=20` +
|
||||||
|
`${agent.config.JUPITER_FEE_BPS ? `&platformFeeBps=${agent.config.JUPITER_FEE_BPS}` : ""}`,
|
||||||
)
|
)
|
||||||
).json();
|
).json();
|
||||||
|
|
||||||
// Get serialized transaction
|
// Get serialized transaction
|
||||||
|
let feeAccount;
|
||||||
|
if (agent.config.JUPITER_REFERRAL_ACCOUNT) {
|
||||||
|
[feeAccount] = PublicKey.findProgramAddressSync(
|
||||||
|
[
|
||||||
|
Buffer.from("referral_ata"),
|
||||||
|
new PublicKey(agent.config.JUPITER_REFERRAL_ACCOUNT).toBuffer(),
|
||||||
|
TOKENS.SOL.toBuffer(),
|
||||||
|
],
|
||||||
|
new PublicKey(JUP_REFERRAL_ADDRESS),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const { swapTransaction } = await (
|
const { swapTransaction } = await (
|
||||||
await fetch("https://quote-api.jup.ag/v6/swap", {
|
await fetch("https://quote-api.jup.ag/v6/swap", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -55,6 +74,7 @@ export async function trade(
|
|||||||
wrapAndUnwrapSol: true,
|
wrapAndUnwrapSol: true,
|
||||||
dynamicComputeUnitLimit: true,
|
dynamicComputeUnitLimit: true,
|
||||||
prioritizationFeeLamports: "auto",
|
prioritizationFeeLamports: "auto",
|
||||||
|
feeAccount: feeAccount ? feeAccount.toString() : null,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
).json();
|
).json();
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { PublicKey } from "@solana/web3.js";
|
import { PublicKey } from "@solana/web3.js";
|
||||||
|
|
||||||
|
export interface Config {
|
||||||
|
OPENAI_API_KEY?: string;
|
||||||
|
JUPITER_REFERRAL_ACCOUNT?: string;
|
||||||
|
JUPITER_FEE_BPS?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Creator {
|
export interface Creator {
|
||||||
address: string;
|
address: string;
|
||||||
percentage: number;
|
percentage: number;
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ async function initializeAgent() {
|
|||||||
const solanaAgent = new SolanaAgentKit(
|
const solanaAgent = new SolanaAgentKit(
|
||||||
process.env.SOLANA_PRIVATE_KEY!,
|
process.env.SOLANA_PRIVATE_KEY!,
|
||||||
process.env.RPC_URL,
|
process.env.RPC_URL,
|
||||||
process.env.OPENAI_API_KEY!,
|
{
|
||||||
|
OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const tools = createSolanaTools(solanaAgent);
|
const tools = createSolanaTools(solanaAgent);
|
||||||
|
|||||||
Reference in New Issue
Block a user