mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-05-17 07:36:45 +00:00
feat:added webhooks for live notifications
This commit is contained in:
@@ -96,6 +96,7 @@ import {
|
||||
OrderParams,
|
||||
FlashTradeParams,
|
||||
FlashCloseTradeParams,
|
||||
PriorityFeeTransaction,
|
||||
HeliusWebhookIdResponse,
|
||||
HeliusWebhookResponse,
|
||||
} from "../types";
|
||||
@@ -687,24 +688,4 @@ export class SolanaAgentKit {
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,150 @@ import {
|
||||
SolanaGetAllAssetsByOwner,
|
||||
} from "./index";
|
||||
|
||||
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",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
return [
|
||||
new SolanaBalanceTool(solanaKit),
|
||||
@@ -172,5 +316,10 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||
new SolanaDeleteHeliusWebhookTool(solanaKit),
|
||||
new SolanaParseTransactionHeliusTool(solanaKit),
|
||||
new SolanaGetAllAssetsByOwner(solanaKit),
|
||||
new Solana3LandCreateSingle(solanaKit),
|
||||
new SolanaSendTransactionWithPriorityFee(solanaKit),
|
||||
new SolanaHeliusWebhookTool(solanaKit),
|
||||
new SolanaGetHeliusWebhookTool(solanaKit),
|
||||
new SolanaDeleteHeliusWebhookTool(solanaKit),
|
||||
];
|
||||
}
|
||||
|
||||
132
src/tools/helius_webhook.ts
Normal file
132
src/tools/helius_webhook.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}`);
|
||||
}
|
||||
}
|
||||
@@ -238,3 +238,20 @@ export interface FlashCloseTradeParams {
|
||||
token: string;
|
||||
side: "long" | "short";
|
||||
}
|
||||
|
||||
export interface PriorityFeeTransaction {
|
||||
transactionId: string;
|
||||
fee: number;
|
||||
}
|
||||
|
||||
export interface HeliusWebhookResponse {
|
||||
webhookURL: string;
|
||||
webhookID: string;
|
||||
}
|
||||
export interface HeliusWebhookIdResponse {
|
||||
wallet: string;
|
||||
webhookURL: string;
|
||||
transactionTypes: string[];
|
||||
accountAddresses: string[];
|
||||
webhookType: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user