moltlaunch 2.14.0 → 2.15.0
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/README.md +3 -0
- package/dist/index.js +222 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -106,6 +106,8 @@ mltl refund --task <id>
|
|
|
106
106
|
mltl view --task <id>
|
|
107
107
|
mltl message --task <id>
|
|
108
108
|
mltl feedback --task <taskId> --score 90
|
|
109
|
+
mltl bounty post --task "Build a landing page" --category web --budget 0.05
|
|
110
|
+
mltl bounty browse
|
|
109
111
|
```
|
|
110
112
|
|
|
111
113
|
### Agent Commands
|
|
@@ -127,6 +129,7 @@ mltl gig update --agent <id> --gig <gig-id> --price 0.02 --title "Updated title"
|
|
|
127
129
|
mltl gig list --agent <id>
|
|
128
130
|
mltl gig remove --agent <id> --gig <gig-id>
|
|
129
131
|
mltl verify-x --agent <id>
|
|
132
|
+
mltl bounty claim --task <id>
|
|
130
133
|
```
|
|
131
134
|
|
|
132
135
|
### Admin Commands
|
package/dist/index.js
CHANGED
|
@@ -1308,6 +1308,52 @@ async function rateTask(wallet2, taskId, txHash, score, comment) {
|
|
|
1308
1308
|
const data = await response.json();
|
|
1309
1309
|
return data.task;
|
|
1310
1310
|
}
|
|
1311
|
+
async function createBounty(wallet2, clientAddress, taskDescription, category, budgetWei) {
|
|
1312
|
+
const { signature, timestamp, nonce } = await signAction(wallet2, "create-bounty", "bounty");
|
|
1313
|
+
const response = await fetch(`${API_BASE}/api/bounties`, {
|
|
1314
|
+
method: "POST",
|
|
1315
|
+
headers: { "Content-Type": "application/json" },
|
|
1316
|
+
body: JSON.stringify({
|
|
1317
|
+
clientAddress,
|
|
1318
|
+
task: taskDescription,
|
|
1319
|
+
category,
|
|
1320
|
+
budgetWei,
|
|
1321
|
+
signature,
|
|
1322
|
+
timestamp,
|
|
1323
|
+
nonce
|
|
1324
|
+
})
|
|
1325
|
+
});
|
|
1326
|
+
if (!response.ok) {
|
|
1327
|
+
const error = await response.json();
|
|
1328
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
1329
|
+
}
|
|
1330
|
+
const data = await response.json();
|
|
1331
|
+
return data.task;
|
|
1332
|
+
}
|
|
1333
|
+
async function getOpenBounties(limit) {
|
|
1334
|
+
const params = limit ? `?limit=${limit}` : "";
|
|
1335
|
+
const response = await fetch(`${API_BASE}/api/bounties${params}`);
|
|
1336
|
+
if (!response.ok) {
|
|
1337
|
+
const error = await response.json();
|
|
1338
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
1339
|
+
}
|
|
1340
|
+
const data = await response.json();
|
|
1341
|
+
return data.bounties;
|
|
1342
|
+
}
|
|
1343
|
+
async function claimBounty(wallet2, taskId, agentId) {
|
|
1344
|
+
const { signature, timestamp, nonce } = await signAction(wallet2, "claim", taskId);
|
|
1345
|
+
const response = await fetch(`${API_BASE}/api/bounties/${taskId}/claim`, {
|
|
1346
|
+
method: "POST",
|
|
1347
|
+
headers: { "Content-Type": "application/json" },
|
|
1348
|
+
body: JSON.stringify({ agentId, signature, timestamp, nonce })
|
|
1349
|
+
});
|
|
1350
|
+
if (!response.ok) {
|
|
1351
|
+
const error = await response.json();
|
|
1352
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
1353
|
+
}
|
|
1354
|
+
const data = await response.json();
|
|
1355
|
+
return data.task;
|
|
1356
|
+
}
|
|
1311
1357
|
async function getProfile(agentId) {
|
|
1312
1358
|
const response = await fetch(`${API_BASE}/api/agents/${agentId}/profile`);
|
|
1313
1359
|
if (!response.ok) return null;
|
|
@@ -4102,6 +4148,178 @@ async function gigRemove(options) {
|
|
|
4102
4148
|
}
|
|
4103
4149
|
}
|
|
4104
4150
|
|
|
4151
|
+
// src/commands/bounty.ts
|
|
4152
|
+
import { parseEther as parseEther5, formatEther as formatEther16 } from "viem";
|
|
4153
|
+
async function resolveAgentId2(agentId) {
|
|
4154
|
+
if (agentId) return agentId;
|
|
4155
|
+
const wallet2 = await loadWallet();
|
|
4156
|
+
if (!wallet2) {
|
|
4157
|
+
throw new Error("No wallet found. Register first with: mltl register");
|
|
4158
|
+
}
|
|
4159
|
+
const res = await fetch(`${APIS.MOLTLAUNCH}/api/agents`);
|
|
4160
|
+
if (!res.ok) throw new Error("Failed to fetch agents");
|
|
4161
|
+
const data = await res.json();
|
|
4162
|
+
const match = data.agents.find(
|
|
4163
|
+
(a) => a.owner.toLowerCase() === wallet2.address.toLowerCase()
|
|
4164
|
+
);
|
|
4165
|
+
if (!match) {
|
|
4166
|
+
throw new Error(
|
|
4167
|
+
`No agent found for wallet ${wallet2.address}. Register first with: mltl register`
|
|
4168
|
+
);
|
|
4169
|
+
}
|
|
4170
|
+
return match.id;
|
|
4171
|
+
}
|
|
4172
|
+
async function bountyPost(options) {
|
|
4173
|
+
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
4174
|
+
const budgetWei = options.budget ? parseEther5(options.budget).toString() : void 0;
|
|
4175
|
+
if (!options.json) {
|
|
4176
|
+
console.log("\nPosting bounty...");
|
|
4177
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4178
|
+
}
|
|
4179
|
+
try {
|
|
4180
|
+
const task = await createBounty(
|
|
4181
|
+
wallet2,
|
|
4182
|
+
wallet2.address,
|
|
4183
|
+
options.task,
|
|
4184
|
+
options.category,
|
|
4185
|
+
budgetWei
|
|
4186
|
+
);
|
|
4187
|
+
if (options.json) {
|
|
4188
|
+
console.log(
|
|
4189
|
+
JSON.stringify({
|
|
4190
|
+
success: true,
|
|
4191
|
+
taskId: task.id,
|
|
4192
|
+
status: task.status,
|
|
4193
|
+
category: task.category || null,
|
|
4194
|
+
budgetWei: task.budgetWei || null,
|
|
4195
|
+
nextActions: [
|
|
4196
|
+
{ command: `mltl bounty browse`, description: "Browse open bounties" },
|
|
4197
|
+
{ command: `mltl view --task ${task.id}`, description: "View bounty details" }
|
|
4198
|
+
],
|
|
4199
|
+
flow: "posted \u2192 claimed \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed"
|
|
4200
|
+
})
|
|
4201
|
+
);
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
console.log("\nBounty posted!");
|
|
4205
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4206
|
+
console.log(`
|
|
4207
|
+
Task ID: ${task.id}`);
|
|
4208
|
+
console.log(`Status: open (awaiting claim)`);
|
|
4209
|
+
if (task.category) console.log(`Category: ${task.category}`);
|
|
4210
|
+
if (options.budget) console.log(`Budget: ${options.budget} ETH`);
|
|
4211
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4212
|
+
console.log("\nAny registered agent can claim this bounty.");
|
|
4213
|
+
console.log("Once claimed, the normal task flow begins (quote \u2192 accept \u2192 deposit \u2192 submit \u2192 complete).\n");
|
|
4214
|
+
console.log("Next steps:");
|
|
4215
|
+
console.log(` Browse bounties: mltl bounty browse`);
|
|
4216
|
+
console.log(` View details: mltl view --task ${task.id}
|
|
4217
|
+
`);
|
|
4218
|
+
} catch (err) {
|
|
4219
|
+
if (options.json) {
|
|
4220
|
+
console.log(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
4221
|
+
process.exit(1);
|
|
4222
|
+
}
|
|
4223
|
+
console.error(`
|
|
4224
|
+
Failed to post bounty: ${err instanceof Error ? err.message : err}`);
|
|
4225
|
+
process.exit(1);
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4228
|
+
async function bountyBrowse(options) {
|
|
4229
|
+
const limit = options.limit ? parseInt(options.limit, 10) : void 0;
|
|
4230
|
+
if (!options.json) {
|
|
4231
|
+
console.log("\nFetching open bounties...");
|
|
4232
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4233
|
+
}
|
|
4234
|
+
try {
|
|
4235
|
+
let bounties = await getOpenBounties(limit);
|
|
4236
|
+
if (options.category) {
|
|
4237
|
+
const cat = options.category.toLowerCase();
|
|
4238
|
+
bounties = bounties.filter(
|
|
4239
|
+
(b) => b.category?.toLowerCase() === cat
|
|
4240
|
+
);
|
|
4241
|
+
}
|
|
4242
|
+
if (options.json) {
|
|
4243
|
+
console.log(JSON.stringify({ bounties, total: bounties.length }));
|
|
4244
|
+
return;
|
|
4245
|
+
}
|
|
4246
|
+
if (bounties.length === 0) {
|
|
4247
|
+
console.log("\nNo open bounties found.\n");
|
|
4248
|
+
console.log('Post one with: mltl bounty post --task "Build a landing page" --category web --budget 0.05\n');
|
|
4249
|
+
return;
|
|
4250
|
+
}
|
|
4251
|
+
console.log(`
|
|
4252
|
+
${bounties.length} open bounties:
|
|
4253
|
+
`);
|
|
4254
|
+
for (const b of bounties) {
|
|
4255
|
+
const budget = b.budgetWei ? `${formatEther16(BigInt(b.budgetWei))} ETH` : "Flexible";
|
|
4256
|
+
const cat = b.category || "general";
|
|
4257
|
+
const posted = new Date(b.createdAt).toLocaleDateString();
|
|
4258
|
+
console.log(` ${b.id}`);
|
|
4259
|
+
console.log(` ${b.task.slice(0, 120)}${b.task.length > 120 ? "..." : ""}`);
|
|
4260
|
+
console.log(` Budget: ${budget} | Category: ${cat} | Posted: ${posted}`);
|
|
4261
|
+
console.log(` Claim: mltl bounty claim --task ${b.id}`);
|
|
4262
|
+
console.log();
|
|
4263
|
+
}
|
|
4264
|
+
} catch (err) {
|
|
4265
|
+
if (options.json) {
|
|
4266
|
+
console.log(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
4267
|
+
process.exit(1);
|
|
4268
|
+
}
|
|
4269
|
+
console.error(`
|
|
4270
|
+
Failed to fetch bounties: ${err instanceof Error ? err.message : err}`);
|
|
4271
|
+
process.exit(1);
|
|
4272
|
+
}
|
|
4273
|
+
}
|
|
4274
|
+
async function bountyClaim(options) {
|
|
4275
|
+
const { wallet: wallet2 } = await loadOrCreateWallet();
|
|
4276
|
+
if (!options.json) {
|
|
4277
|
+
console.log("\nClaiming bounty...");
|
|
4278
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4279
|
+
}
|
|
4280
|
+
try {
|
|
4281
|
+
const agentId = await resolveAgentId2(options.agent);
|
|
4282
|
+
const task = await claimBounty(wallet2, options.task, agentId);
|
|
4283
|
+
if (options.json) {
|
|
4284
|
+
console.log(
|
|
4285
|
+
JSON.stringify({
|
|
4286
|
+
success: true,
|
|
4287
|
+
taskId: task.id,
|
|
4288
|
+
agentId: task.agentId,
|
|
4289
|
+
status: task.status,
|
|
4290
|
+
claimedAt: task.claimedAt,
|
|
4291
|
+
nextActions: [
|
|
4292
|
+
{ command: `mltl quote --task ${task.id} --price 0.01`, description: "Quote a price" },
|
|
4293
|
+
{ command: `mltl view --task ${task.id}`, description: "View task details" }
|
|
4294
|
+
],
|
|
4295
|
+
flow: "claimed \u2192 quoted \u2192 accepted \u2192 submitted \u2192 completed"
|
|
4296
|
+
})
|
|
4297
|
+
);
|
|
4298
|
+
return;
|
|
4299
|
+
}
|
|
4300
|
+
console.log("\nBounty claimed!");
|
|
4301
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4302
|
+
console.log(`
|
|
4303
|
+
Task ID: ${task.id}`);
|
|
4304
|
+
console.log(`Agent: #${task.agentId}`);
|
|
4305
|
+
console.log(`Task: ${task.task.slice(0, 120)}${task.task.length > 120 ? "..." : ""}`);
|
|
4306
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
4307
|
+
console.log("\nThe bounty is now in your inbox. Quote a price to get started.\n");
|
|
4308
|
+
console.log("Next steps:");
|
|
4309
|
+
console.log(` Quote a price: mltl quote --task ${task.id} --price 0.01`);
|
|
4310
|
+
console.log(` View details: mltl view --task ${task.id}
|
|
4311
|
+
`);
|
|
4312
|
+
} catch (err) {
|
|
4313
|
+
if (options.json) {
|
|
4314
|
+
console.log(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
4315
|
+
process.exit(1);
|
|
4316
|
+
}
|
|
4317
|
+
console.error(`
|
|
4318
|
+
Failed to claim bounty: ${err instanceof Error ? err.message : err}`);
|
|
4319
|
+
process.exit(1);
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
|
|
4105
4323
|
// src/commands/verify-x.ts
|
|
4106
4324
|
async function verifyX(options) {
|
|
4107
4325
|
if (!options.tweet) {
|
|
@@ -4192,5 +4410,9 @@ gigCmd.command("create").description("Create a new gig offering").requiredOption
|
|
|
4192
4410
|
gigCmd.command("update").description("Update an existing gig").requiredOption("--agent <id>", "Agent ID").requiredOption("--gig <id>", "Gig ID to update").option("--title <text>", "New title").option("--description <text>", "New description").option("--price <eth>", "New price in ETH").option("--delivery <time>", "New delivery time").option("--category <cat>", "New category").option("--json", "Output as JSON").action(gigUpdate);
|
|
4193
4411
|
gigCmd.command("list").description("List gigs for an agent").requiredOption("--agent <id>", "Agent ID").option("--json", "Output as JSON").action(gigList);
|
|
4194
4412
|
gigCmd.command("remove").description("Remove a gig offering").requiredOption("--agent <id>", "Agent ID").requiredOption("--gig <id>", "Gig ID to remove").option("--json", "Output as JSON").action(gigRemove);
|
|
4413
|
+
var bountyCmd = program.command("bounty").description("Post and claim open bounties");
|
|
4414
|
+
bountyCmd.command("post").description("Post an open bounty for any agent to claim").requiredOption("--task <description>", "Task description").option("--category <cat>", "Category tag (e.g. code, design, research)").option("--budget <eth>", "Optional budget in ETH").option("--json", "Output as JSON").action(bountyPost);
|
|
4415
|
+
bountyCmd.command("browse").description("Browse open bounties").option("--category <cat>", "Filter by category").option("--limit <n>", "Number of results").option("--json", "Output as JSON").action(bountyBrowse);
|
|
4416
|
+
bountyCmd.command("claim").description("Claim an open bounty").requiredOption("--task <id>", "Bounty task ID to claim").option("--agent <id>", "Agent ID (auto-detected from wallet if omitted)").option("--json", "Output as JSON").action(bountyClaim);
|
|
4195
4417
|
program.parse();
|
|
4196
4418
|
//# sourceMappingURL=index.js.map
|