Skip to content

Commit

Permalink
Helius sdk (#160)
Browse files Browse the repository at this point in the history
# Pull Request Description

## Related Issue
Fixes #157 

## Changes Made
This PR adds the following changes:
<!-- List the key changes made in this PR -->
- Added tool to parse Transactions in human readable format
- Get all assets owned by a Public key
- Create , Get and Delete Webhooks for real time notifications
- Send a transaction with priority fee using Helius API
  
## Implementation Details
<!-- Provide technical details about the implementation -->
- Used Helius API's to implement the changes


## Transaction executed by agent 
<!-- If applicable, provide example usage, transactions, or screenshots
-->
![Screenshot 2025-01-07
160320](https://github.com/user-attachments/assets/66327de0-c069-45d4-88d4-3891bef61eca)
![Screenshot 2025-01-07
170044](https://github.com/user-attachments/assets/f90ae856-f43b-4ab6-8905-1b7ad28ac2d7)
![Screenshot 2025-01-09
012651](https://github.com/user-attachments/assets/242db155-c3b8-4bcf-953f-a7a0fe9aada7)
![Screenshot 2025-01-09
012730](https://github.com/user-attachments/assets/d98c1589-5716-4068-bee8-be01cb27b4cc)
![Screenshot 2025-01-09
021915](https://github.com/user-attachments/assets/98ffdf1b-86fb-4ff1-b62f-9eb32d1d0ecb)
![Screenshot 2025-01-10
151839](https://github.com/user-attachments/assets/bb36ca67-d6b3-4cc0-b514-282cc765c6c1)
Transaction id for priority fee 
```34iEaLyeQc71rrv5bwV49LkfxbsYqFeWS3rV7wxKM2MHiNrfj9QxkdfFjkquBdneubyp6PsNVATRSit4ATseGKtH```




## Prompt Used
<!-- If relevant, include the prompt or configuration used -->
```parse this transaction for me
5Mp5eVCdjY2i4uk7oEs3kKSqNab49cauuJANuQhiNq9tWKPRe7QmS65amhTGzYfMGfoNB64kY3Jjzrh8Fy4D8FV6```
```give me assets owned by this address BVdNLvyG2DNiWAXBE9qAmc4MTQXymd5Bzfo9xrQSUzVP limit 3```
```send 0.0001 sol to Eo2ciguhMLmcTWXELuEQPdu7DWZt67LHXb2rdHZUbot7 with
high priority```


## Additional Notes
<!-- Any additional information that reviewers should know -->

## Checklist
- [x] I have tested these changes locally
- [ ] I have updated the documentation
- [x] I have added a transaction link
- [x] I have added the prompt used to test it
  • Loading branch information
thearyanag authored Jan 13, 2025
2 parents fcbb2e1 + 20360ba commit a32959f
Show file tree
Hide file tree
Showing 27 changed files with 1,862 additions and 864 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ RPC_URL=
SOLANA_PRIVATE_KEY=
JUPITER_REFERRAL_ACCOUNT=
JUPITER_FEE_BPS=
FLASH_PRIVILEGE= referral | nft | none
FLASH_PRIVILEGE= referral | nft | none
HELIUS_API_KEY=
1,501 changes: 646 additions & 855 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions src/actions/helius/createWebhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { create_HeliusWebhook } from "../../tools/helius";

const createWebhookAction: Action = {
name: "CREATE_HELIOUS_WEBHOOK",
similes: ["setup webhook", "register webhook", "initiate webhook"],
description:
"Creates a new webhook in the Helius system to monitor transactions for specified account addresses",
examples: [
[
{
input: {
accountAddresses: [
"BVdNLvyG2DNiWAXBE9qAmc4MTQXymd5Bzfo9xrQSUzVP",
"Eo2ciguhMLmcTWXELuEQPdu7DWZt67LHXb2rdHZUbot7",
],
webhookURL: "https://yourdomain.com/webhook",
},
output: {
status: "success",
webhookURL: "https://yourdomain.com/webhook",
webhookID: "webhook_123",
message: "Webhook created successfully.",
},
explanation:
"Creates a Webhook to send live notifications on the given Url with the wallet Addresses.",
},
],
],
schema: z.object({
accountAddresses: z
.array(z.string())
.min(1)
.describe("List of Solana account public keys to monitor"),
webhookURL: z
.string()
.url()
.describe("The URL where Helius will send webhook notifications"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
const response = await create_HeliusWebhook(
agent,
input.accountAddresses,
input.webhookURL,
);

return {
status: "success",
...response,
message: "Webhook created successfully.",
};
},
};

export default createWebhookAction;
40 changes: 40 additions & 0 deletions src/actions/helius/deleteWebhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { deleteHeliusWebhook } from "../../tools/helius";

const deleteWebhookAction: Action = {
name: "DELETE_HELIOUS_WEBHOOK",
similes: ["remove webhook", "unregister webhook", "delete webhook"],
description: "Deletes a Helius webhook by its unique ID",
examples: [
[
{
input: {
webhookID: "webhook_123",
},
output: {
status: "success",
message: "Webhook deleted successfully.",
},
explanation: "Permanently removes a Helius webhook.",
},
],
],
schema: z.object({
webhookID: z
.string()
.min(1)
.describe("The unique identifier of the Helius webhook to delete"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
const result = await deleteHeliusWebhook(agent, input.webhookID);

return {
status: "success",
message: result.message || "Webhook deleted successfully.",
};
},
};

export default deleteWebhookAction;
75 changes: 75 additions & 0 deletions src/actions/helius/getAssetsbyOwner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Action } from "../../types/action";
import { PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { getAssetsByOwner } from "../../tools/helius";

const getAssetsByOwnerAction: Action = {
name: "FETCH_ASSETS_BY_OWNER",
similes: [
"fetch assets",
"get assets",
"retrieve assets",
"list assets",
"assets by owner",
],
description:
"Fetch assets owned by a specific Solana wallet address using the Helius Digital Asset Standard API",
examples: [
[
{
input: {
ownerPublicKey: "4Pf8q3mHGLdkoc1M8xWZwW5q32gYmdhwC2gJ8K9EAGDX",
limit: 10,
},
output: {
status: "success",
assets: [
{
name: "Helius NFT #1",
type: "NFT",
owner: "4Pf8q3mHGLdkoc1M8xWZwW5q32gYmdhwC2gJ8K9EAGDX",
},
{
name: "Helius Token #10",
type: "Token",
owner: "4Pf8q3mHGLdkoc1M8xWZwW5q32gYmdhwC2gJ8K9EAGDX",
},
],
message: "Successfully fetched assets for the wallet address",
},
explanation:
"Fetches a list of assets from the for the given wallet address with a limit of 10 items.",
},
],
],
schema: z.object({
ownerPublicKey: z.string().describe("Owner's Solana wallet PublicKey"),
limit: z
.number()
.positive()
.describe("Number of assets to retrieve per request"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const assets = await getAssetsByOwner(
agent,
new PublicKey(input.ownerPublicKey),
input.limit,
);

return {
status: "success",
assets: assets,
message: `Successfully fetched assets for the wallet address: ${input.ownerPublicKey}`,
};
} catch (error: any) {
return {
status: "error",
message: `Failed to fetch assets: ${error.message}`,
};
}
},
};

export default getAssetsByOwnerAction;
47 changes: 47 additions & 0 deletions src/actions/helius/getWebhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { getHeliusWebhook } from "../../tools/helius";

const getWebhookAction: Action = {
name: "GET_HELIOUS_WEBHOOK",
similes: ["fetch webhook details", "retrieve webhook", "get webhook info"],
description: "Retrieves details of a Helius webhook by its unique ID",
examples: [
[
{
input: {
webhookID: "webhook_123",
},
output: {
status: "success",
wallet: "WalletPublicKey",
webhookURL: "https://yourdomain.com/webhook",
transactionTypes: ["Any"],
accountAddresses: ["SomePublicKey", "AnotherPublicKey"],
webhookType: "enhanced",
message: "Webhook details retrieved successfully.",
},
explanation:
"Retrieves detailed information about an existing Helius webhook, including the wallet address it monitors, the types of transactions it tracks, and the specific webhook URL.",
},
],
],
schema: z.object({
webhookID: z
.string()
.min(1)
.describe("The unique identifier of the Helius webhook to retrieve"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
const webhookDetails = await getHeliusWebhook(agent, input.webhookID);

return {
status: "success",
...webhookDetails,
message: "Webhook details retrieved successfully.",
};
},
};

export default getWebhookAction;
65 changes: 65 additions & 0 deletions src/actions/helius/parseTransaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { parseTransaction } from "../../tools/helius";

const parseSolanaTransactionAction: Action = {
name: "PARSE_SOLANA_TRANSACTION",
similes: [
"parse transaction",
"analyze transaction",
"inspect transaction",
"decode transaction",
],
description:
"Parse a Solana transaction to retrieve detailed information using the Helius Enhanced Transactions API",
examples: [
[
{
input: {
transactionId:
"4zZVvbgzcriyjAeEiK1w7CeDCt7gYThUCZat3ULTNerzKHF4WLfRG2YUjbRovfFJ639TAyARB4oyRDcLVUvrakq7",
},
output: {
status: "success",
transaction: {
details: "Transaction details...",
involvedAccounts: ["Account1", "Account2"],
executedOperations: [{ operation: "Transfer", amount: "1000 SOL" }],
},
message:
"Successfully parsed transaction: 4zZVvbgzcriyjAeEiK1w7CeDCt7gYThUCZat3ULTNerzKHF4WLfRG2YUjbRovfFJ639TAyARB4oyRDcLVUvrakq7",
},
explanation:
"Parse a Transaction to transform it into human readable format.",
},
],
],
schema: z.object({
transactionId: z
.string()
.min(1)
.describe("The Solana transaction ID to parse"),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const parsedTransactionData = await parseTransaction(
agent,
input.transactionId,
);

return {
status: "success",
transaction: parsedTransactionData,
message: `Successfully parsed transaction: ${input.transactionId}`,
};
} catch (error: any) {
return {
status: "error",
message: `Failed to parse transaction: ${error.message}`,
};
}
},
};

export default parseSolanaTransactionAction;
76 changes: 76 additions & 0 deletions src/actions/helius/sendTransactionWithPriority.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Action } from "../../types/action";
import { SolanaAgentKit } from "../../agent";
import { z } from "zod";
import { sendTransactionWithPriorityFee } from "../../tools/helius";
import { PublicKey } from "@solana/web3.js";

const sendTransactionWithPriorityFeeAction: Action = {
name: "SEND_TRANSACTION_WITH_PRIORITY_FEE",
similes: [
"send SOL with fee",
"transfer tokens with priority",
"execute priority transaction",
],
description:
"Sends SOL or SPL tokens from a wallet with an estimated priority fee, ensuring faster processing on the Solana network.",
examples: [
[
{
input: {
priorityLevel: "High",
amount: 2,
to: "BVdNLvyG2DNiWAXBE9qAmc4MTQXymd5Bzfo9xrQSUzVP",
splmintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
},
output: {
status: "success",
transactionId: "5Xgq9xVABhwXpNStWpfqxS6Vm5Eau91pjfeHNwJbRgis",
fee: 5000,
message: "Transaction sent with priority fee successfully.",
},
explanation:
"Sends 2 USDC to BVdNLvyG2DNiWAXBE9qAmc4MTQXymd5Bzfo9xrQSUzVP with High priority fee option.",
},
],
],
schema: z.object({
priorityLevel: z
.enum(["Min", "Low", "Medium", "High", "VeryHigh", "UnsafeMax"])
.describe("Priority level to determine the urgency of the transaction."),
amount: z
.number()
.positive()
.describe("Amount of SOL or SPL tokens to send."),
to: z.string().describe("Recipient's PublicKey."),
splmintAddress: z
.string()
.optional()
.describe(
"Optional SPL token address, if transferring tokens other than SOL.",
),
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
const { priorityLevel, amount, to, splmintAddress } = input;
const toPublicKey = new PublicKey(to);
const splmintPublicKey = splmintAddress
? new PublicKey(splmintAddress)
: undefined;

const result = await sendTransactionWithPriorityFee(
agent,
priorityLevel,
amount,
toPublicKey,
splmintPublicKey,
);

return {
status: "success",
transactionId: result.transactionId,
fee: result.fee,
message: "Transaction sent with priority fee successfully.",
};
},
};

export default sendTransactionWithPriorityFeeAction;
Loading

0 comments on commit a32959f

Please sign in to comment.