Skip to content

Commit 16f7dc6

Browse files
authored
feat: Implement framework-independent Action interface (#72)
This PR implements a framework-independent Action interface inspired by Eliza, making the tools more flexible and reusable across different frameworks. Changes: - Created independent actions under `src/actions/` - Implemented Zod validation for type safety - Converted all LangChain tools to use actions - Added natural language matching with similes - Improved error handling and response formats
2 parents 15034ac + 9bf1755 commit 16f7dc6

40 files changed

+2540
-18
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
"form-data": "^4.0.1",
5454
"langchain": "^0.3.8",
5555
"openai": "^4.77.0",
56-
"typedoc": "^0.27.6"
56+
"typedoc": "^0.27.6",
57+
"zod": "^3.24.1"
5758
},
5859
"devDependencies": {
5960
"@types/bn.js": "^5.1.6",

pnpm-lock.yaml

Lines changed: 4 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/actions/balance.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { PublicKey } from "@solana/web3.js";
2+
import { Action } from "../types/action";
3+
import { SolanaAgentKit } from "../agent";
4+
import { z } from "zod";
5+
import { get_balance } from "../tools";
6+
7+
const balanceAction: Action = {
8+
name: "solana_balance",
9+
similes: [
10+
"check balance",
11+
"get wallet balance",
12+
"view balance",
13+
"show balance",
14+
"check token balance",
15+
],
16+
description: `Get the balance of a Solana wallet or token account.
17+
If you want to get the balance of your wallet, you don't need to provide the tokenAddress.
18+
If no tokenAddress is provided, the balance will be in SOL.`,
19+
examples: [
20+
[
21+
{
22+
input: {},
23+
output: {
24+
status: "success",
25+
balance: "100",
26+
token: "SOL",
27+
},
28+
explanation: "Get SOL balance of the wallet",
29+
},
30+
],
31+
[
32+
{
33+
input: {
34+
tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
35+
},
36+
output: {
37+
status: "success",
38+
balance: "1000",
39+
token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
40+
},
41+
explanation: "Get USDC token balance",
42+
},
43+
],
44+
],
45+
schema: z.object({
46+
tokenAddress: z.string().optional(),
47+
}),
48+
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
49+
const balance = await get_balance(
50+
agent,
51+
input.tokenAddress && new PublicKey(input.tokenAddress),
52+
);
53+
54+
return {
55+
status: "success",
56+
balance: balance,
57+
token: input.tokenAddress || "SOL",
58+
};
59+
},
60+
};
61+
62+
export default balanceAction;

src/actions/compressedAirdrop.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { Action } from "../types/action";
2+
import { SolanaAgentKit } from "../agent";
3+
import { z } from "zod";
4+
import { sendCompressedAirdrop } from "../tools";
5+
6+
const compressedAirdropAction: Action = {
7+
name: "solana_compressed_airdrop",
8+
similes: [
9+
"ZK Compressed airdrop",
10+
"Airdrop tokens with compression",
11+
"Send compressed SPL airdrop",
12+
"Airdrop to multiple recipients",
13+
],
14+
description:
15+
"Airdrop SPL tokens with ZK Compression (also known as airdropping tokens) to multiple recipients",
16+
examples: [
17+
[
18+
{
19+
input: {
20+
mintAddress: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN",
21+
amount: 42,
22+
decimals: 6,
23+
recipients: [
24+
"1nc1nerator11111111111111111111111111111111",
25+
"BrFndAe111111111111111111111111111111111",
26+
],
27+
priorityFeeInLamports: 30000,
28+
shouldLog: true,
29+
},
30+
output: {
31+
status: "success",
32+
message: "Airdropped 42 tokens to 2 recipients.",
33+
transactionHashes: ["4uyfBN...", "9XsF2N..."],
34+
},
35+
explanation:
36+
"Airdrops 42 tokens (with 6 decimals) to 2 recipients, optionally logging progress to stdout.",
37+
},
38+
],
39+
],
40+
// Validate inputs with zod
41+
schema: z.object({
42+
mintAddress: z
43+
.string()
44+
.min(1)
45+
.describe("Mint address of the token, e.g., 'JUPy...'"),
46+
amount: z
47+
.number()
48+
.positive()
49+
.describe("Number of tokens to airdrop per recipient, e.g., 42"),
50+
decimals: z
51+
.number()
52+
.nonnegative()
53+
.int()
54+
.describe("Decimals of the token, e.g., 6"),
55+
recipients: z
56+
.array(z.string())
57+
.nonempty()
58+
.describe("Array of recipient addresses, e.g., ['1nc1n...']"),
59+
priorityFeeInLamports: z
60+
.number()
61+
.optional()
62+
.describe("Priority fee in lamports (default is 30_000)"),
63+
shouldLog: z
64+
.boolean()
65+
.optional()
66+
.describe("Whether to log progress to stdout (default is false)"),
67+
}),
68+
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
69+
try {
70+
const {
71+
mintAddress,
72+
amount,
73+
decimals,
74+
recipients,
75+
priorityFeeInLamports,
76+
shouldLog,
77+
} = input;
78+
79+
// Call your airdrop method on the SolanaAgentKit
80+
const txs = await sendCompressedAirdrop(
81+
mintAddress,
82+
amount,
83+
decimals,
84+
recipients,
85+
priorityFeeInLamports || 30_000,
86+
shouldLog || false,
87+
);
88+
89+
return {
90+
status: "success",
91+
message: `Airdropped ${amount} tokens to ${recipients.length} recipients.`,
92+
transactionHashes: txs,
93+
};
94+
} catch (error: any) {
95+
return {
96+
status: "error",
97+
message: `Failed to airdrop tokens: ${error.message}`,
98+
code: error.code || "UNKNOWN_ERROR",
99+
};
100+
}
101+
},
102+
};
103+
104+
export default compressedAirdropAction;

src/actions/createGibworkTask.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { Action } from "../types/action";
2+
import { SolanaAgentKit } from "../agent";
3+
import { z } from "zod";
4+
import { PublicKey } from "@solana/web3.js";
5+
import { create_gibwork_task } from "../tools";
6+
7+
const createGibworkTaskAction: Action = {
8+
name: "solana_create_gibwork_task",
9+
similes: [
10+
"create task",
11+
"post job",
12+
"create gig",
13+
"post task",
14+
"create work",
15+
"new task on gibwork",
16+
],
17+
description:
18+
"Create a new task on the Gibwork platform with payment in SPL tokens",
19+
examples: [
20+
[
21+
{
22+
input: {
23+
title: "Build a Solana dApp",
24+
content: "Create a simple Solana dApp with React frontend",
25+
requirements: "Experience with Rust and React",
26+
tags: ["solana", "rust", "react"],
27+
tokenMintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
28+
tokenAmount: 100,
29+
},
30+
output: {
31+
status: "success",
32+
taskId: "task_123",
33+
signature: "3YKpM1...",
34+
message: "Successfully created task: Build a Solana dApp",
35+
},
36+
explanation: "Create a new task on Gibwork with 100 USDC payment",
37+
},
38+
],
39+
],
40+
schema: z.object({
41+
title: z.string().min(1).describe("Title of the task"),
42+
content: z.string().min(1).describe("Description of the task"),
43+
requirements: z
44+
.string()
45+
.min(1)
46+
.describe("Requirements to complete the task"),
47+
tags: z
48+
.array(z.string())
49+
.min(1)
50+
.describe("List of tags associated with the task"),
51+
tokenMintAddress: z.string().describe("Token mint address for payment"),
52+
tokenAmount: z.number().positive().describe("Payment amount for the task"),
53+
payer: z
54+
.string()
55+
.optional()
56+
.describe("Optional payer address (defaults to wallet address)"),
57+
}),
58+
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
59+
try {
60+
const responseData = await create_gibwork_task(
61+
agent,
62+
input.title,
63+
input.content,
64+
input.requirements,
65+
input.tags,
66+
new PublicKey(input.tokenMintAddress),
67+
input.tokenAmount,
68+
input.payer ? new PublicKey(input.payer) : undefined,
69+
);
70+
71+
return {
72+
status: "success",
73+
taskId: responseData.taskId,
74+
signature: responseData.signature,
75+
message: `Successfully created task: ${input.title}`,
76+
};
77+
} catch (error: any) {
78+
return {
79+
status: "error",
80+
message: `Failed to create task: ${error.message}`,
81+
};
82+
}
83+
},
84+
};
85+
86+
export default createGibworkTaskAction;

0 commit comments

Comments
 (0)