@bountyagents/bountyagents-task 2026.2.277 → 2026.2.278
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.local +1 -0
- package/dist/index.js +52504 -39529
- package/index.ts +44 -87
- package/package.json +1 -1
- package/src/helper.ts +6 -0
- package/src/publisher.ts +241 -0
- package/test-plugin.ts +39 -0
package/index.ts
CHANGED
|
@@ -1,94 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PrivateKeySigner } from "./src/signers.js";
|
|
3
|
-
import crypto from "node:crypto";
|
|
4
|
-
import { Type } from "@sinclair/typebox";
|
|
1
|
+
import { registerPublisherTools } from "./src/publisher.js";
|
|
5
2
|
|
|
6
3
|
export default function register(api: any) {
|
|
7
|
-
api.registerCommand({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
// api.registerCommand({
|
|
5
|
+
// name: "task",
|
|
6
|
+
// description: "Bounty Agents Task commands",
|
|
7
|
+
// acceptsArgs: true,
|
|
8
|
+
// handler: async (ctx: any) => {
|
|
9
|
+
// const args = ctx.args?.trim() ?? "";
|
|
10
|
+
// const tokens = args.split(/\s+/).filter(Boolean);
|
|
11
|
+
// const action = (tokens[0] ?? "status").toLowerCase();
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
// if (action === "create") {
|
|
14
|
+
// const signer = new PrivateKeySigner(
|
|
15
|
+
// "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
|
16
|
+
// );
|
|
17
|
+
// const plugin = new BountyAgentsPublisherPlugin(signer, {
|
|
18
|
+
// serviceUrl: "http://localhost:3000",
|
|
19
|
+
// contractAddress: "0x55D45aFA265d0381C8A81328FfeA408D2Dd45F40",
|
|
20
|
+
// });
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
22
|
+
// try {
|
|
23
|
+
// const task = (await plugin.executeTool(
|
|
24
|
+
// "bountyagents.publisher.task.create",
|
|
25
|
+
// {
|
|
26
|
+
// id: crypto.randomUUID(),
|
|
27
|
+
// title: "Test Task from CLI",
|
|
28
|
+
// content: "This is a test task created via the CLI tool.",
|
|
29
|
+
// }
|
|
30
|
+
// )) as any;
|
|
31
|
+
// console.log("Task created successfully:", task);
|
|
32
|
+
// return {
|
|
33
|
+
// text: `Task created successfully: ${task.id}`,
|
|
34
|
+
// };
|
|
35
|
+
// } catch (error) {
|
|
36
|
+
// console.error("Failed to create task:", error);
|
|
37
|
+
// return {
|
|
38
|
+
// text: "Failed to create task:",
|
|
39
|
+
// error: error,
|
|
40
|
+
// };
|
|
41
|
+
// }
|
|
42
|
+
// }
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
44
|
+
// return {
|
|
45
|
+
// text: ["Bounty Agents Task commands:", "", "/task create"].join("\n"),
|
|
46
|
+
// };
|
|
47
|
+
// },
|
|
48
|
+
// });
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
name: "create_bounty_task",
|
|
55
|
-
description:
|
|
56
|
-
"Create a draft bounty task for an agent based on user request, tell user to give title and content of the task, and return the created task id to user if successful",
|
|
57
|
-
parameters: Type.Object({
|
|
58
|
-
title: Type.String(),
|
|
59
|
-
content: Type.String(),
|
|
60
|
-
}),
|
|
61
|
-
async execute(_id: string, params: any) {
|
|
62
|
-
const signer = new PrivateKeySigner(
|
|
63
|
-
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
|
64
|
-
);
|
|
65
|
-
const plugin = new BountyAgentsPublisherPlugin(signer, {
|
|
66
|
-
serviceUrl: "http://localhost:3000",
|
|
67
|
-
contractAddress: "0x55D45aFA265d0381C8A81328FfeA408D2Dd45F40",
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
const task = (await plugin.executeTool(
|
|
72
|
-
"bountyagents.publisher.task.create",
|
|
73
|
-
{
|
|
74
|
-
id: crypto.randomUUID(),
|
|
75
|
-
title: params.title,
|
|
76
|
-
content: params.content,
|
|
77
|
-
}
|
|
78
|
-
)) as any;
|
|
79
|
-
return {
|
|
80
|
-
content: [
|
|
81
|
-
{ type: "text", text: `Task created successfully! ID: ${task.id}` },
|
|
82
|
-
],
|
|
83
|
-
};
|
|
84
|
-
} catch (error: any) {
|
|
85
|
-
return {
|
|
86
|
-
content: [
|
|
87
|
-
{ type: "text", text: `Failed to create task: ${error.message}` },
|
|
88
|
-
],
|
|
89
|
-
isError: true,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
});
|
|
50
|
+
registerPublisherTools(api);
|
|
94
51
|
}
|
package/package.json
CHANGED
package/src/helper.ts
ADDED
package/src/publisher.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { createPublicClient, createWalletClient, http, parseUnits } from "viem";
|
|
3
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
4
|
+
import { bscTestnet } from "viem/chains";
|
|
5
|
+
import { taskDepositKey } from "./escrow.js";
|
|
6
|
+
import { json } from "./helper.js";
|
|
7
|
+
import { BountyAgentsPublisherPlugin } from "./index.js";
|
|
8
|
+
import { PrivateKeySigner } from "./signers.js";
|
|
9
|
+
|
|
10
|
+
const SERVICE_URL = "http://localhost:3000";
|
|
11
|
+
const CONTRACT_ADDRESS = "0x55D45aFA265d0381C8A81328FfeA408D2Dd45F40";
|
|
12
|
+
const PRIVATE_KEY =
|
|
13
|
+
"0x289f92dd30c36ff24b75b48623c70dea2b428dabac7a52c5ca810bcda64d861b";
|
|
14
|
+
const TEST_TOKEN_ADDRESS = "0x56DA32693A4e6dDd0eDC932b295cb00372f37f8b";
|
|
15
|
+
|
|
16
|
+
const AGENT_ESCROW_ABI = [
|
|
17
|
+
{
|
|
18
|
+
inputs: [
|
|
19
|
+
{ name: "key", type: "bytes32" },
|
|
20
|
+
{ name: "token", type: "address" },
|
|
21
|
+
{ name: "amount", type: "uint256" },
|
|
22
|
+
],
|
|
23
|
+
name: "deposit",
|
|
24
|
+
outputs: [],
|
|
25
|
+
stateMutability: "nonpayable",
|
|
26
|
+
type: "function",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
inputs: [{ name: "key", type: "bytes32" }],
|
|
30
|
+
name: "getDeposit",
|
|
31
|
+
outputs: [
|
|
32
|
+
{
|
|
33
|
+
components: [
|
|
34
|
+
{ name: "owner", type: "address" },
|
|
35
|
+
{ name: "token", type: "address" },
|
|
36
|
+
{ name: "amountLocked", type: "uint256" },
|
|
37
|
+
{ name: "released", type: "bool" },
|
|
38
|
+
],
|
|
39
|
+
name: "",
|
|
40
|
+
type: "tuple",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
stateMutability: "view",
|
|
44
|
+
type: "function",
|
|
45
|
+
},
|
|
46
|
+
] as const;
|
|
47
|
+
|
|
48
|
+
const ERC20_ABI = [
|
|
49
|
+
{
|
|
50
|
+
inputs: [
|
|
51
|
+
{ name: "spender", type: "address" },
|
|
52
|
+
{ name: "amount", type: "uint256" },
|
|
53
|
+
],
|
|
54
|
+
name: "approve",
|
|
55
|
+
outputs: [{ name: "", type: "bool" }],
|
|
56
|
+
stateMutability: "nonpayable",
|
|
57
|
+
type: "function",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
inputs: [],
|
|
61
|
+
name: "decimals",
|
|
62
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
63
|
+
stateMutability: "view",
|
|
64
|
+
type: "function",
|
|
65
|
+
},
|
|
66
|
+
] as const;
|
|
67
|
+
|
|
68
|
+
export async function createBountyTask(params: {
|
|
69
|
+
title: string;
|
|
70
|
+
content: string;
|
|
71
|
+
}) {
|
|
72
|
+
const signer = new PrivateKeySigner(PRIVATE_KEY);
|
|
73
|
+
const plugin = new BountyAgentsPublisherPlugin(signer, {
|
|
74
|
+
serviceUrl: SERVICE_URL,
|
|
75
|
+
contractAddress: CONTRACT_ADDRESS,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const task = (await plugin.executeTool("bountyagents.publisher.task.create", {
|
|
79
|
+
id: crypto.randomUUID(),
|
|
80
|
+
title: params.title,
|
|
81
|
+
content: params.content,
|
|
82
|
+
})) as any;
|
|
83
|
+
return task;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function fundBountyTask(params: {
|
|
87
|
+
taskId: string;
|
|
88
|
+
price: string;
|
|
89
|
+
token: string;
|
|
90
|
+
}) {
|
|
91
|
+
const signer = new PrivateKeySigner(PRIVATE_KEY);
|
|
92
|
+
const plugin = new BountyAgentsPublisherPlugin(signer, {
|
|
93
|
+
serviceUrl: SERVICE_URL,
|
|
94
|
+
contractAddress: CONTRACT_ADDRESS,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const task = (await plugin.executeTool("bountyagents.publisher.task.fund", {
|
|
98
|
+
taskId: params.taskId,
|
|
99
|
+
price: params.price,
|
|
100
|
+
token: params.token,
|
|
101
|
+
})) as any;
|
|
102
|
+
return task;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function depositToken(params: {
|
|
106
|
+
taskId: string;
|
|
107
|
+
amount?: string;
|
|
108
|
+
}) {
|
|
109
|
+
const account = privateKeyToAccount(PRIVATE_KEY);
|
|
110
|
+
const chain = bscTestnet;
|
|
111
|
+
const transport = http();
|
|
112
|
+
|
|
113
|
+
const walletClient = createWalletClient({
|
|
114
|
+
account,
|
|
115
|
+
chain,
|
|
116
|
+
transport,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const publicClient = createPublicClient({
|
|
120
|
+
chain,
|
|
121
|
+
transport,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Fetch decimals from the token contract
|
|
125
|
+
console.log(`Fetching decimals for token ${TEST_TOKEN_ADDRESS}...`);
|
|
126
|
+
const decimals = await publicClient.readContract({
|
|
127
|
+
address: TEST_TOKEN_ADDRESS as `0x${string}`,
|
|
128
|
+
abi: ERC20_ABI,
|
|
129
|
+
functionName: "decimals",
|
|
130
|
+
});
|
|
131
|
+
console.log(`Token decimals: ${decimals}`);
|
|
132
|
+
|
|
133
|
+
const amount = parseUnits(params.amount || "100", decimals);
|
|
134
|
+
|
|
135
|
+
const depositKey = taskDepositKey(params.taskId);
|
|
136
|
+
console.log(`Deposit key: ${depositKey}`);
|
|
137
|
+
|
|
138
|
+
// 1. Approve
|
|
139
|
+
console.log(`Approving ${params.amount || "100"} tokens...`);
|
|
140
|
+
const approveHash = await walletClient.writeContract({
|
|
141
|
+
address: TEST_TOKEN_ADDRESS as `0x${string}`,
|
|
142
|
+
abi: ERC20_ABI,
|
|
143
|
+
functionName: "approve",
|
|
144
|
+
args: [CONTRACT_ADDRESS as `0x${string}`, amount],
|
|
145
|
+
});
|
|
146
|
+
console.log(`Approve transaction sent: ${approveHash}`);
|
|
147
|
+
console.log(`Waiting for confirmation...`);
|
|
148
|
+
await publicClient.waitForTransactionReceipt({ hash: approveHash });
|
|
149
|
+
console.log(`Approve confirmed!`);
|
|
150
|
+
|
|
151
|
+
// 2. Deposit
|
|
152
|
+
console.log(`Depositing tokens into AgentEscrow...`);
|
|
153
|
+
const depositHash = await walletClient.writeContract({
|
|
154
|
+
address: CONTRACT_ADDRESS as `0x${string}`,
|
|
155
|
+
abi: AGENT_ESCROW_ABI,
|
|
156
|
+
functionName: "deposit",
|
|
157
|
+
args: [depositKey, TEST_TOKEN_ADDRESS as `0x${string}`, amount],
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await publicClient.waitForTransactionReceipt({ hash: depositHash });
|
|
161
|
+
console.log(`Deposit confirmed!`);
|
|
162
|
+
|
|
163
|
+
const depositInfo = await publicClient.readContract({
|
|
164
|
+
address: CONTRACT_ADDRESS as `0x${string}`,
|
|
165
|
+
abi: AGENT_ESCROW_ABI,
|
|
166
|
+
functionName: "getDeposit",
|
|
167
|
+
args: [depositKey],
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
message: `Successfully deposited ${params.amount || "100"} test tokens`,
|
|
172
|
+
taskId: params.taskId,
|
|
173
|
+
approveTransactionHash: approveHash,
|
|
174
|
+
depositTransactionHash: depositHash,
|
|
175
|
+
rawAmount: amount.toString(),
|
|
176
|
+
rawLockedAmount: depositInfo.amountLocked.toString(),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function registerPublisherTools(api: any) {
|
|
181
|
+
api.registerTool({
|
|
182
|
+
name: "create_bounty_task",
|
|
183
|
+
description:
|
|
184
|
+
"Create a draft bounty task for an agent based on user request, tell user to give title and content of the task, and return the created task id to user if successful",
|
|
185
|
+
parameters: Type.Object({
|
|
186
|
+
title: Type.String(),
|
|
187
|
+
content: Type.String(),
|
|
188
|
+
}),
|
|
189
|
+
async execute(_id: string, params: any) {
|
|
190
|
+
try {
|
|
191
|
+
const result = await createBountyTask(params);
|
|
192
|
+
return json(result);
|
|
193
|
+
} catch (error: any) {
|
|
194
|
+
return json({
|
|
195
|
+
error: error instanceof Error ? error.message : String(error),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
api.registerTool({
|
|
202
|
+
name: "deposit_token",
|
|
203
|
+
description:
|
|
204
|
+
"Deposit test tokens into the AgentEscrow contract for a specific task.",
|
|
205
|
+
parameters: Type.Object({
|
|
206
|
+
taskId: Type.String(),
|
|
207
|
+
amount: Type.Optional(Type.String()),
|
|
208
|
+
}),
|
|
209
|
+
async execute(_id: string, params: any) {
|
|
210
|
+
try {
|
|
211
|
+
const result = await depositToken(params);
|
|
212
|
+
return json(result);
|
|
213
|
+
} catch (error: any) {
|
|
214
|
+
return json({
|
|
215
|
+
error: error instanceof Error ? error.message : String(error),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
api.registerTool({
|
|
222
|
+
name: "fund_bounty_task",
|
|
223
|
+
description:
|
|
224
|
+
"Fund a draft bounty task, attaching price and token metadata to it. The token must be in the format 'network:address'.",
|
|
225
|
+
parameters: Type.Object({
|
|
226
|
+
taskId: Type.String(),
|
|
227
|
+
price: Type.String(),
|
|
228
|
+
token: Type.String(),
|
|
229
|
+
}),
|
|
230
|
+
async execute(_id: string, params: any) {
|
|
231
|
+
try {
|
|
232
|
+
const result = await fundBountyTask(params);
|
|
233
|
+
return json(result);
|
|
234
|
+
} catch (error: any) {
|
|
235
|
+
return json({
|
|
236
|
+
error: error instanceof Error ? error.message : String(error),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
}
|
package/test-plugin.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { depositToken, createBountyTask, fundBountyTask } from "./src/publisher.js";
|
|
2
|
+
|
|
3
|
+
async function testCreateAndDeposit() {
|
|
4
|
+
const testId = "test-" + Date.now();
|
|
5
|
+
console.log(`\n--- Testing createBountyTask ---`);
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const taskResult = await createBountyTask({
|
|
9
|
+
title: `Test Task ${testId}`,
|
|
10
|
+
content: "This is a test task content created via standalone function."
|
|
11
|
+
});
|
|
12
|
+
console.log("Task creation successful!");
|
|
13
|
+
console.log(JSON.stringify(taskResult, null, 2));
|
|
14
|
+
|
|
15
|
+
const createdTaskId = taskResult.id;
|
|
16
|
+
console.log(`\n--- Testing depositToken with taskId: ${createdTaskId} ---`);
|
|
17
|
+
|
|
18
|
+
const depositResult = await depositToken({
|
|
19
|
+
taskId: createdTaskId,
|
|
20
|
+
amount: "100"
|
|
21
|
+
});
|
|
22
|
+
console.log("Deposit successful!");
|
|
23
|
+
console.log(JSON.stringify(depositResult, null, 2));
|
|
24
|
+
|
|
25
|
+
console.log(`\n--- Testing fundBountyTask with taskId: ${createdTaskId} ---`);
|
|
26
|
+
const fundResult = await fundBountyTask({
|
|
27
|
+
taskId: createdTaskId,
|
|
28
|
+
price: depositResult.rawLockedAmount,
|
|
29
|
+
token: "bsc-testnet:0x56DA32693A4e6dDd0eDC932b295cb00372f37f8b"
|
|
30
|
+
});
|
|
31
|
+
console.log("Fund task successful!");
|
|
32
|
+
console.log(JSON.stringify(fundResult, null, 2));
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("Test failed:");
|
|
35
|
+
console.error(error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
testCreateAndDeposit();
|