mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-05-14 07:26:46 +00:00
refactored code
This commit is contained in:
@@ -76,6 +76,12 @@ import {
|
||||
multisig_reject_proposal,
|
||||
multisig_approve_proposal,
|
||||
multisig_execute_proposal,
|
||||
parseTransaction,
|
||||
sendTransactionWithPriorityFee,
|
||||
getAssetsByOwner,
|
||||
getHeliusWebhook,
|
||||
create_HeliusWebhook,
|
||||
deleteHeliusWebhook,
|
||||
} from "../tools";
|
||||
import {
|
||||
Config,
|
||||
@@ -90,6 +96,8 @@ import {
|
||||
OrderParams,
|
||||
FlashTradeParams,
|
||||
FlashCloseTradeParams,
|
||||
HeliusWebhookIdResponse,
|
||||
HeliusWebhookResponse,
|
||||
} from "../types";
|
||||
|
||||
/**
|
||||
@@ -654,4 +662,36 @@ export class SolanaAgentKit {
|
||||
): Promise<string> {
|
||||
return multisig_execute_proposal(this, transactionIndex);
|
||||
}
|
||||
async CreateWebhook(
|
||||
accountAddresses: string[],
|
||||
webhookURL: string,
|
||||
): Promise<HeliusWebhookResponse> {
|
||||
return create_HeliusWebhook(this, accountAddresses, webhookURL);
|
||||
}
|
||||
async getWebhook(id: string): Promise<HeliusWebhookIdResponse> {
|
||||
return getHeliusWebhook(this, id);
|
||||
}
|
||||
async deleteWebhook(webhookID: string): Promise<any> {
|
||||
return deleteHeliusWebhook(this, webhookID);
|
||||
}
|
||||
async heliusParseTransactions(transactionId: string): Promise<any> {
|
||||
return parseTransaction(this, transactionId);
|
||||
}
|
||||
async getAllAssetsbyOwner(owner: PublicKey, limit: number): Promise<any> {
|
||||
return getAssetsByOwner(this, owner, limit);
|
||||
}
|
||||
async sendTranctionWithPriority(
|
||||
priorityLevel: string,
|
||||
amount: number,
|
||||
to: PublicKey,
|
||||
splmintAddress?: PublicKey,
|
||||
): Promise<{ transactionId: string; fee: number }> {
|
||||
return sendTransactionWithPriorityFee(
|
||||
this,
|
||||
priorityLevel,
|
||||
amount,
|
||||
to,
|
||||
splmintAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
65
src/langchain/helius/create_webhook.ts
Normal file
65
src/langchain/helius/create_webhook.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
|
||||
export class SolanaHeliusWebhookTool extends Tool {
|
||||
name = "create_helius_webhook";
|
||||
description = `Creates a Helius Webhook that listens to specified account addresses.
|
||||
Inputs (input is a JSON string):
|
||||
accountAddresses: string[] | string,
|
||||
e.g. ["BVdNLvyG2DNiWAXBE9qAmc4MTQXymd5Bzfo9xrQSUzVP","Eo2ciguhMLmcTWXELuEQPdu7DWZt67LHXb2rdHZUbot7"]
|
||||
or "BVdNLvyG2DNiWAXBE9qAmc4MTQXymd5Bzfo9xrQSUzVP,Eo2ciguhMLmcTWXELuEQPdu7DWZt67LHXb2rdHZUbot7"
|
||||
webhookURL: string, e.g. "https://TestServer.test.repl.co/webhooks"`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const parsedInput = JSON.parse(input);
|
||||
let accountAddresses: string[] = [];
|
||||
|
||||
if (!parsedInput.accountAddresses) {
|
||||
throw new Error('Missing "accountAddresses" property in input JSON.');
|
||||
}
|
||||
if (Array.isArray(parsedInput.accountAddresses)) {
|
||||
accountAddresses = parsedInput.accountAddresses.map((addr: string) =>
|
||||
addr.trim(),
|
||||
);
|
||||
} else if (typeof parsedInput.accountAddresses === "string") {
|
||||
accountAddresses = parsedInput.accountAddresses
|
||||
.split(",")
|
||||
.map((addr: string) => addr.trim());
|
||||
} else {
|
||||
throw new Error(
|
||||
'Invalid type for "accountAddresses". Expected array or comma-separated string.',
|
||||
);
|
||||
}
|
||||
|
||||
const webhookURL = parsedInput.webhookURL;
|
||||
if (!webhookURL) {
|
||||
throw new Error(
|
||||
'Invalid input. Expected a "webhookURL" property in the JSON.',
|
||||
);
|
||||
}
|
||||
const result = await this.solanaKit.CreateWebhook(
|
||||
accountAddresses,
|
||||
webhookURL,
|
||||
);
|
||||
|
||||
// Return success in JSON
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Helius Webhook created successfully",
|
||||
webhookURL: result.webhookURL,
|
||||
webhookID: result.webhookID,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/langchain/helius/delete_webhook.ts
Normal file
39
src/langchain/helius/delete_webhook.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
|
||||
export class SolanaDeleteHeliusWebhookTool extends Tool {
|
||||
name = "delete_helius_webhook";
|
||||
description = `Deletes a Helius Webhook by its ID.
|
||||
Inputs (input is a JSON string):
|
||||
webhookID: string, e.g. "1ed4244d-a591-4854-ac31-cc28d40b8255"`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const parsedInput = JSON.parse(input);
|
||||
|
||||
const webhookID = parsedInput.webhookID;
|
||||
if (!webhookID || typeof webhookID !== "string") {
|
||||
throw new Error(
|
||||
'Invalid input. Expected a "webhookID" property in the JSON.',
|
||||
);
|
||||
}
|
||||
const result = await this.solanaKit.deleteWebhook(webhookID);
|
||||
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Helius Webhook deleted successfully",
|
||||
data: result,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/langchain/helius/get_all_assets.ts
Normal file
38
src/langchain/helius/get_all_assets.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
export class SolanaGetAllAssetsByOwner extends Tool {
|
||||
name = "solana_get_all_assets_by_owner";
|
||||
description = `Get all assets owned by a specific wallet address.
|
||||
Inputs:
|
||||
- owner: string, the wallet address of the owner, e.g., "4Be9CvxqHW6BYiRAxW9Q3xu1ycTMWaL5z8NX4HR3ha7t" (required)
|
||||
- limit: number, the maximum number of assets to retrieve (optional)`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const { owner, limit } = JSON.parse(input);
|
||||
const ownerPubkey = new PublicKey(owner);
|
||||
|
||||
const assets = await this.solanaKit.getAllAssetsbyOwner(
|
||||
ownerPubkey,
|
||||
limit,
|
||||
);
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Assets retrieved successfully",
|
||||
assets: assets,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/langchain/helius/get_webhook.ts
Normal file
43
src/langchain/helius/get_webhook.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
|
||||
export class SolanaGetHeliusWebhookTool extends Tool {
|
||||
name = "get_helius_webhook";
|
||||
description = `Retrieves a Helius Webhook by its ID.
|
||||
Inputs (input is a JSON string):
|
||||
webhookID: string, e.g. "1ed4244d-a591-4854-ac31-cc28d40b8255"`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const parsedInput = JSON.parse(input);
|
||||
|
||||
const webhookID = parsedInput.webhookID;
|
||||
if (!webhookID || typeof webhookID !== "string") {
|
||||
throw new Error(
|
||||
'Invalid input. Expected a "webhookID" property in the JSON.',
|
||||
);
|
||||
}
|
||||
|
||||
const result = await this.solanaKit.getWebhook(webhookID);
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Helius Webhook retrieved successfully",
|
||||
wallet: result.wallet,
|
||||
webhookURL: result.webhookURL,
|
||||
transactionTypes: result.transactionTypes,
|
||||
accountAddresses: result.accountAddresses,
|
||||
webhookType: result.webhookType,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/langchain/helius/index.ts
Normal file
6
src/langchain/helius/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from "./create_webhook";
|
||||
export * from "./delete_webhook";
|
||||
export * from "./get_all_assets";
|
||||
export * from "./get_webhook";
|
||||
export * from "./parse_transaction";
|
||||
export * from "./send_transaction_priority";
|
||||
32
src/langchain/helius/parse_transaction.ts
Normal file
32
src/langchain/helius/parse_transaction.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
|
||||
export class SolanaParseTransactionHeliusTool extends Tool {
|
||||
name = "solana_parse_transaction_helius";
|
||||
description = `Parse a Solana transaction using Helius API.
|
||||
Inputs:
|
||||
- transactionId: string, the ID of the transaction to parse, e.g., "5h3k...9d2k" (required).`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<any> {
|
||||
try {
|
||||
const transactionId = input.trim();
|
||||
const parsedTransaction =
|
||||
await this.solanaKit.heliusParseTransactions(transactionId);
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "transaction parsed successfully",
|
||||
transaction: parsedTransaction,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "NOt able to Parse transaction",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
63
src/langchain/helius/send_transaction_priority.ts
Normal file
63
src/langchain/helius/send_transaction_priority.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Tool } from "langchain/tools";
|
||||
import { SolanaAgentKit } from "../../agent";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
export class SolanaSendTransactionWithPriorityFee extends Tool {
|
||||
name = "solana_send_transaction_with_priority_fee";
|
||||
description = `Sends a Solana transaction with a user-defined priority fee.
|
||||
**Inputs (JSON-encoded string)**:
|
||||
- priorityLevel: string — the priority level ("NONE", "Min", "Low", "Medium", "High", "VeryHigh", or "UnsafeMax")
|
||||
- amount: number — the amount of SOL to send
|
||||
- to: string — the recipient's wallet address (public key in base58);`;
|
||||
|
||||
constructor(private solanaKit: SolanaAgentKit) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async _call(input: string): Promise<string> {
|
||||
try {
|
||||
const { priorityLevel, amount, to, splmintAddress } = JSON.parse(input);
|
||||
|
||||
const validPriorityLevels = [
|
||||
"NONE",
|
||||
"Min",
|
||||
"Low",
|
||||
"Medium",
|
||||
"High",
|
||||
"VeryHigh",
|
||||
"UnsafeMax",
|
||||
];
|
||||
if (!validPriorityLevels.includes(priorityLevel)) {
|
||||
throw new Error(
|
||||
`Invalid priority level. Must be one of: ${validPriorityLevels.join(", ")}. Received: ${priorityLevel}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!amount || !to) {
|
||||
throw new Error(
|
||||
`Missing required fields. Received: priorityLevel=${priorityLevel}, amount=${amount}, to=${to}`,
|
||||
);
|
||||
}
|
||||
|
||||
const toPubkey = new PublicKey(to);
|
||||
const priorityFeeTx = await this.solanaKit.sendTranctionWithPriority(
|
||||
priorityLevel,
|
||||
amount,
|
||||
toPubkey,
|
||||
splmintAddress,
|
||||
);
|
||||
|
||||
return JSON.stringify({
|
||||
status: "success",
|
||||
message: "Transaction sent successfully",
|
||||
priorityFeeTx,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return JSON.stringify({
|
||||
status: "error",
|
||||
message: error.message,
|
||||
code: error.code || "UNKNOWN_ERROR",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ export * from "./tiplink";
|
||||
export * from "./sns";
|
||||
export * from "./lightprotocol";
|
||||
export * from "./squads";
|
||||
export * from "./helius";
|
||||
|
||||
import { SolanaAgentKit } from "../agent";
|
||||
import {
|
||||
@@ -91,6 +92,12 @@ import {
|
||||
SolanaApproveProposal2by2Multisig,
|
||||
SolanaExecuteProposal2by2Multisig,
|
||||
SolanaRejectProposal2by2Multisig,
|
||||
SolanaSendTransactionWithPriorityFee,
|
||||
SolanaHeliusWebhookTool,
|
||||
SolanaGetHeliusWebhookTool,
|
||||
SolanaDeleteHeliusWebhookTool,
|
||||
SolanaParseTransactionHeliusTool,
|
||||
SolanaGetAllAssetsByOwner,
|
||||
} from "./index";
|
||||
|
||||
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
@@ -159,5 +166,11 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
new SolanaExecuteProposal2by2Multisig(solanaKit),
|
||||
new SolanaDepositTo2by2Multisig(solanaKit),
|
||||
new SolanaTransferFrom2by2Multisig(solanaKit),
|
||||
new SolanaSendTransactionWithPriorityFee(solanaKit),
|
||||
new SolanaHeliusWebhookTool(solanaKit),
|
||||
new SolanaGetHeliusWebhookTool(solanaKit),
|
||||
new SolanaDeleteHeliusWebhookTool(solanaKit),
|
||||
new SolanaParseTransactionHeliusTool(solanaKit),
|
||||
new SolanaGetAllAssetsByOwner(solanaKit),
|
||||
];
|
||||
}
|
||||
|
||||
57
src/tools/helius/get_assets_by_owner.ts
Normal file
57
src/tools/helius/get_assets_by_owner.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { SolanaAgentKit } from "../../index";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
/**
|
||||
* Fetch assets by owner using the Helius Digital Asset Standard (DAS) API
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param ownerPublicKey Owner's Solana wallet PublicKey
|
||||
* @param limit Number of assets to retrieve per request
|
||||
* @returns Assets owned by the specified address
|
||||
*/
|
||||
export async function getAssetsByOwner(
|
||||
agent: SolanaAgentKit,
|
||||
ownerPublicKey: PublicKey,
|
||||
limit: number,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const apiKey = agent.config.HELIUS_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("HELIUS_API_KEY not found in environment variables");
|
||||
}
|
||||
|
||||
const url = `https://mainnet.helius-rpc.com/?api-key=${apiKey}`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: "get-assets",
|
||||
method: "getAssetsByOwner",
|
||||
params: {
|
||||
ownerAddress: ownerPublicKey.toString(),
|
||||
page: 3,
|
||||
limit: limit,
|
||||
displayOptions: {
|
||||
showFungible: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch: ${response.status} - ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data.result.items;
|
||||
} catch (error: any) {
|
||||
console.error("Error retrieving assets: ", error.message);
|
||||
throw new Error(`Assets retrieval failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
44
src/tools/helius/helius_transaction_parsing.ts
Normal file
44
src/tools/helius/helius_transaction_parsing.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { SolanaAgentKit } from "../../index";
|
||||
|
||||
/**
|
||||
* Parse a Solana transaction using the Helius Enhanced Transactions API
|
||||
* @param agent SolanaAgentKit instance
|
||||
* @param transactionId The transaction ID to parse
|
||||
* @returns Parsed transaction data
|
||||
*/
|
||||
export async function parseTransaction(
|
||||
agent: SolanaAgentKit,
|
||||
transactionId: string,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const apiKey = agent.config.HELIUS_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("HELIUS_API_KEY not found in environment variables");
|
||||
}
|
||||
|
||||
const url = `https://api.helius.xyz/v0/transactions/?api-key=${apiKey}`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
transactions: [transactionId],
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch: ${response.status} - ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} catch (error: any) {
|
||||
console.error("Error parsing transaction: ", error.message);
|
||||
throw new Error(`Transaction parsing failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
132
src/tools/helius/helius_webhooks.ts
Normal file
132
src/tools/helius/helius_webhooks.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { SolanaAgentKit } from "../../index";
|
||||
import { HeliusWebhookResponse, HeliusWebhookIdResponse } from "../../index";
|
||||
|
||||
export async function create_HeliusWebhook(
|
||||
agent: SolanaAgentKit,
|
||||
accountAddresses: string[],
|
||||
webhookURL: string,
|
||||
): Promise<HeliusWebhookResponse> {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://api.helius.xyz/v0/webhooks?api-key=${agent.config.HELIUS_API_KEY}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
webhookURL,
|
||||
transactionTypes: ["Any"],
|
||||
accountAddresses,
|
||||
webhookType: "enhanced",
|
||||
txnStatus: "all",
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
webhookURL: data.webhookURL,
|
||||
webhookID: data.webhookID,
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to create Webhook: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a Helius Webhook by ID, returning only the specified fields.
|
||||
*
|
||||
* @param agent - An instance of SolanaAgentKit (with .config.HELIUS_API_KEY)
|
||||
* @param webhookID - The unique ID of the webhook to retrieve
|
||||
*
|
||||
* @returns A HeliusWebhook object containing { wallet, webhookURL, transactionTypes, accountAddresses, webhookType }
|
||||
*/
|
||||
export async function getHeliusWebhook(
|
||||
agent: SolanaAgentKit,
|
||||
webhookID: string,
|
||||
): Promise<HeliusWebhookIdResponse> {
|
||||
try {
|
||||
const apiKey = agent.config.HELIUS_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("HELIUS_API_KEY is missing in agent.config");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`https://api.helius.xyz/v0/webhooks/${webhookID}?api-key=${apiKey}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch webhook with ID ${webhookID}. ` +
|
||||
`Status Code: ${response.status}`,
|
||||
);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return {
|
||||
wallet: data.wallet,
|
||||
webhookURL: data.webhookURL,
|
||||
transactionTypes: data.transactionTypes,
|
||||
accountAddresses: data.accountAddresses,
|
||||
webhookType: data.webhookType,
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to get webhook by ID: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a Helius Webhook by its ID.
|
||||
*
|
||||
* @param agent - An instance of SolanaAgentKit (with .config.HELIUS_API_KEY)
|
||||
* @param webhookID - The unique ID of the webhook to delete
|
||||
*
|
||||
* @returns The response body from the Helius API (which may contain status or other info)
|
||||
*/
|
||||
export async function deleteHeliusWebhook(
|
||||
agent: SolanaAgentKit,
|
||||
webhookID: string,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const apiKey = agent.config.HELIUS_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("Missing Helius API key in agent.config.HELIUS_API_KEY");
|
||||
}
|
||||
|
||||
const url = `https://api.helius.xyz/v0/webhooks/${webhookID}?api-key=${apiKey}`;
|
||||
const response = await fetch(url, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to delete webhook: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
if (response.status === 204) {
|
||||
return { message: "Webhook deleted successfully (no content returned)" };
|
||||
}
|
||||
const contentLength = response.headers.get("Content-Length");
|
||||
if (contentLength === "0" || !contentLength) {
|
||||
return { message: "Webhook deleted successfully (empty body)" };
|
||||
}
|
||||
|
||||
// Otherwise, parse as JSON
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error: any) {
|
||||
console.error("Error deleting Helius Webhook:", error.message);
|
||||
throw new Error(`Failed to delete Helius Webhook: ${error.message}`);
|
||||
}
|
||||
}
|
||||
4
src/tools/helius/index.ts
Normal file
4
src/tools/helius/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from "./get_assets_by_owner";
|
||||
export * from "./helius_transaction_parsing";
|
||||
export * from "./helius_webhooks";
|
||||
export * from "./send_transaction_with_priority";
|
||||
174
src/tools/helius/send_transaction_with_priority.ts
Normal file
174
src/tools/helius/send_transaction_with_priority.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
import { SolanaAgentKit, PriorityFeeResponse } from "../../index";
|
||||
import {
|
||||
SystemProgram,
|
||||
Transaction,
|
||||
sendAndConfirmTransaction,
|
||||
ComputeBudgetProgram,
|
||||
PublicKey,
|
||||
LAMPORTS_PER_SOL,
|
||||
} from "@solana/web3.js";
|
||||
import {
|
||||
getAssociatedTokenAddress,
|
||||
createTransferInstruction,
|
||||
getMint,
|
||||
createAssociatedTokenAccountInstruction,
|
||||
} from "@solana/spl-token";
|
||||
import bs58 from "bs58";
|
||||
|
||||
/**
|
||||
* Sends a transaction with an estimated priority fee using the provided SolanaAgentKit.
|
||||
*
|
||||
* @param agent An instance of SolanaAgentKit containing connection, wallet, etc.
|
||||
* @param priorityLevel The priority level (e.g., "Min", "Low", "Medium", "High", "VeryHigh", or "UnsafeMax").
|
||||
* @param amount The amount of SOL to send (in SOL, not lamports).
|
||||
* @param to The recipient's PublicKey.
|
||||
* @returns The transaction signature (string) once confirmed along with the fee used.
|
||||
*/
|
||||
export async function sendTransactionWithPriorityFee(
|
||||
agent: SolanaAgentKit,
|
||||
priorityLevel: string,
|
||||
amount: number,
|
||||
to: PublicKey,
|
||||
splmintAddress?: PublicKey,
|
||||
): Promise<{ transactionId: string; fee: number }> {
|
||||
try {
|
||||
if (!splmintAddress) {
|
||||
const transaction = new Transaction();
|
||||
const { blockhash, lastValidBlockHeight } =
|
||||
await agent.connection.getLatestBlockhash();
|
||||
transaction.recentBlockhash = blockhash;
|
||||
transaction.lastValidBlockHeight = lastValidBlockHeight;
|
||||
transaction.feePayer = agent.wallet_address;
|
||||
|
||||
const transferIx = SystemProgram.transfer({
|
||||
fromPubkey: agent.wallet_address,
|
||||
toPubkey: to,
|
||||
lamports: amount * LAMPORTS_PER_SOL,
|
||||
});
|
||||
|
||||
transaction.add(transferIx);
|
||||
transaction.sign(agent.wallet);
|
||||
|
||||
const response = await fetch(
|
||||
`https://mainnet.helius-rpc.com/?api-key=${agent.config.HELIUS_API_KEY}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: "1",
|
||||
method: "getPriorityFeeEstimate",
|
||||
params: [
|
||||
{
|
||||
transaction: bs58.encode(transaction.serialize()),
|
||||
options: { priorityLevel: priorityLevel },
|
||||
},
|
||||
],
|
||||
} as PriorityFeeResponse),
|
||||
},
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error("Error fetching priority fee:");
|
||||
}
|
||||
const feeEstimate: number = data.result.priorityFeeEstimate;
|
||||
|
||||
// Set the priority fee if applicable
|
||||
const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
|
||||
microLamports: feeEstimate,
|
||||
});
|
||||
transaction.add(computePriceIx);
|
||||
|
||||
// Send the transaction and confirm
|
||||
const txSignature = await sendAndConfirmTransaction(
|
||||
agent.connection,
|
||||
transaction,
|
||||
[agent.wallet],
|
||||
);
|
||||
|
||||
return {
|
||||
transactionId: txSignature,
|
||||
fee: feeEstimate,
|
||||
};
|
||||
} else {
|
||||
const fromAta = await getAssociatedTokenAddress(
|
||||
splmintAddress,
|
||||
agent.wallet_address,
|
||||
);
|
||||
const toAta = await getAssociatedTokenAddress(splmintAddress, to);
|
||||
|
||||
const mintInfo = await getMint(agent.connection, splmintAddress);
|
||||
const adjustedAmount = amount * Math.pow(10, mintInfo.decimals);
|
||||
|
||||
const transaction = new Transaction();
|
||||
const { blockhash, lastValidBlockHeight } =
|
||||
await agent.connection.getLatestBlockhash();
|
||||
transaction.recentBlockhash = blockhash;
|
||||
transaction.lastValidBlockHeight = lastValidBlockHeight;
|
||||
transaction.feePayer = agent.wallet_address;
|
||||
|
||||
const response = await fetch(
|
||||
`https://mainnet.helius-rpc.com/?api-key=${agent.config.HELIUS_API_KEY}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: "1",
|
||||
method: "getPriorityFeeEstimate",
|
||||
params: [
|
||||
{
|
||||
transaction: bs58.encode(transaction.serialize()),
|
||||
options: { priorityLevel: priorityLevel },
|
||||
},
|
||||
],
|
||||
} as PriorityFeeResponse),
|
||||
},
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error("Error fetching priority fee:");
|
||||
}
|
||||
const feeEstimate: number = data.result.priorityFeeEstimate;
|
||||
|
||||
transaction.add(
|
||||
ComputeBudgetProgram.setComputeUnitPrice({
|
||||
microLamports: feeEstimate,
|
||||
}),
|
||||
);
|
||||
|
||||
transaction.add(
|
||||
createAssociatedTokenAccountInstruction(
|
||||
agent.wallet_address,
|
||||
toAta,
|
||||
to,
|
||||
splmintAddress,
|
||||
),
|
||||
);
|
||||
|
||||
transaction.add(
|
||||
createTransferInstruction(
|
||||
fromAta,
|
||||
toAta,
|
||||
agent.wallet_address,
|
||||
adjustedAmount,
|
||||
),
|
||||
);
|
||||
|
||||
const txSignature = await sendAndConfirmTransaction(
|
||||
agent.connection,
|
||||
transaction,
|
||||
[agent.wallet],
|
||||
);
|
||||
|
||||
return {
|
||||
transactionId: txSignature,
|
||||
fee: feeEstimate,
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to process transaction: ${error.message}`);
|
||||
}
|
||||
}
|
||||
@@ -23,3 +23,5 @@ export * from "./3land";
|
||||
export * from "./tiplink";
|
||||
export * from "./lightprotocol";
|
||||
export * from "./squads";
|
||||
export * from "./squads_multisig";
|
||||
export * from "./helius";
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface Config {
|
||||
JUPITER_REFERRAL_ACCOUNT?: string;
|
||||
JUPITER_FEE_BPS?: number;
|
||||
FLASH_PRIVILEGE?: string;
|
||||
HELIUS_API_KEY?: string;
|
||||
}
|
||||
|
||||
export interface Creator {
|
||||
@@ -237,3 +238,25 @@ export interface FlashCloseTradeParams {
|
||||
token: string;
|
||||
side: "long" | "short";
|
||||
}
|
||||
|
||||
export interface HeliusWebhookResponse {
|
||||
webhookURL: string;
|
||||
webhookID: string;
|
||||
}
|
||||
export interface HeliusWebhookIdResponse {
|
||||
wallet: string;
|
||||
webhookURL: string;
|
||||
transactionTypes: string[];
|
||||
accountAddresses: string[];
|
||||
webhookType: string;
|
||||
}
|
||||
|
||||
export interface PriorityFeeResponse {
|
||||
jsonrpc: string;
|
||||
id: string;
|
||||
method: string;
|
||||
params: Array<{
|
||||
transaction: string;
|
||||
options: { priorityLevel: string };
|
||||
}>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user