mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-06-02 23:26:50 +00:00
refactored code
This commit is contained in:
@@ -76,6 +76,12 @@ import {
|
|||||||
multisig_reject_proposal,
|
multisig_reject_proposal,
|
||||||
multisig_approve_proposal,
|
multisig_approve_proposal,
|
||||||
multisig_execute_proposal,
|
multisig_execute_proposal,
|
||||||
|
parseTransaction,
|
||||||
|
sendTransactionWithPriorityFee,
|
||||||
|
getAssetsByOwner,
|
||||||
|
getHeliusWebhook,
|
||||||
|
create_HeliusWebhook,
|
||||||
|
deleteHeliusWebhook,
|
||||||
} from "../tools";
|
} from "../tools";
|
||||||
import {
|
import {
|
||||||
Config,
|
Config,
|
||||||
@@ -90,6 +96,8 @@ import {
|
|||||||
OrderParams,
|
OrderParams,
|
||||||
FlashTradeParams,
|
FlashTradeParams,
|
||||||
FlashCloseTradeParams,
|
FlashCloseTradeParams,
|
||||||
|
HeliusWebhookIdResponse,
|
||||||
|
HeliusWebhookResponse,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -654,4 +662,36 @@ export class SolanaAgentKit {
|
|||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return multisig_execute_proposal(this, transactionIndex);
|
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 "./sns";
|
||||||
export * from "./lightprotocol";
|
export * from "./lightprotocol";
|
||||||
export * from "./squads";
|
export * from "./squads";
|
||||||
|
export * from "./helius";
|
||||||
|
|
||||||
import { SolanaAgentKit } from "../agent";
|
import { SolanaAgentKit } from "../agent";
|
||||||
import {
|
import {
|
||||||
@@ -91,6 +92,12 @@ import {
|
|||||||
SolanaApproveProposal2by2Multisig,
|
SolanaApproveProposal2by2Multisig,
|
||||||
SolanaExecuteProposal2by2Multisig,
|
SolanaExecuteProposal2by2Multisig,
|
||||||
SolanaRejectProposal2by2Multisig,
|
SolanaRejectProposal2by2Multisig,
|
||||||
|
SolanaSendTransactionWithPriorityFee,
|
||||||
|
SolanaHeliusWebhookTool,
|
||||||
|
SolanaGetHeliusWebhookTool,
|
||||||
|
SolanaDeleteHeliusWebhookTool,
|
||||||
|
SolanaParseTransactionHeliusTool,
|
||||||
|
SolanaGetAllAssetsByOwner,
|
||||||
} from "./index";
|
} from "./index";
|
||||||
|
|
||||||
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
||||||
@@ -159,5 +166,11 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
|
|||||||
new SolanaExecuteProposal2by2Multisig(solanaKit),
|
new SolanaExecuteProposal2by2Multisig(solanaKit),
|
||||||
new SolanaDepositTo2by2Multisig(solanaKit),
|
new SolanaDepositTo2by2Multisig(solanaKit),
|
||||||
new SolanaTransferFrom2by2Multisig(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 "./tiplink";
|
||||||
export * from "./lightprotocol";
|
export * from "./lightprotocol";
|
||||||
export * from "./squads";
|
export * from "./squads";
|
||||||
|
export * from "./squads_multisig";
|
||||||
|
export * from "./helius";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export interface Config {
|
|||||||
JUPITER_REFERRAL_ACCOUNT?: string;
|
JUPITER_REFERRAL_ACCOUNT?: string;
|
||||||
JUPITER_FEE_BPS?: number;
|
JUPITER_FEE_BPS?: number;
|
||||||
FLASH_PRIVILEGE?: string;
|
FLASH_PRIVILEGE?: string;
|
||||||
|
HELIUS_API_KEY?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Creator {
|
export interface Creator {
|
||||||
@@ -237,3 +238,25 @@ export interface FlashCloseTradeParams {
|
|||||||
token: string;
|
token: string;
|
||||||
side: "long" | "short";
|
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 };
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ async function initializeAgent() {
|
|||||||
process.env.RPC_URL!,
|
process.env.RPC_URL!,
|
||||||
{
|
{
|
||||||
OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
|
OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
|
||||||
|
HELIUS_API_KEY: process.env.HELIUS_API_KEY!,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user