Skip to content

Commit 1197a40

Browse files
plur9claude
andcommitted
feat: add ade skills sales command for inventory monitoring
Ported from fairdrop MCP's check_sales tool. Shows available copies, total sales, and low-stock alerts for a seller's active skill listings. Usage: ade skills sales <seller_address> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1066b49 commit 1197a40

3 files changed

Lines changed: 67 additions & 1 deletion

File tree

src/commands.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,50 @@ export async function skillsShow(id: string) {
257257
return apiFetch(`/skills/${encodeURIComponent(id)}`)
258258
}
259259

260+
export async function skillsSales(sellerAddress: string) {
261+
if (!isAddress(sellerAddress)) {
262+
throw new CLIError('ERR_INVALID_ARGUMENT', 'Invalid seller address', 'Provide a valid Ethereum address (0x...)')
263+
}
264+
265+
const data = await apiFetch<{ items: Array<{ id: string; title: string; total_sales: number; escrow_id: number | null }> }>(
266+
`/skills?seller=${encodeURIComponent(sellerAddress)}&status=active&limit=50`
267+
)
268+
269+
const skills = data.items ?? []
270+
const results = await Promise.all(skills.map(async (skill) => {
271+
try {
272+
const info = await apiFetch<{ status: string; available_copies?: number; total_sales?: number }>(
273+
`/skills/${encodeURIComponent(skill.id)}/purchase-info`
274+
)
275+
return {
276+
skill_id: skill.id,
277+
title: skill.title,
278+
status: info.status,
279+
available: info.available_copies ?? 0,
280+
total_sales: info.total_sales ?? skill.total_sales,
281+
needs_restock: (info.available_copies ?? 0) <= 1,
282+
}
283+
} catch {
284+
return {
285+
skill_id: skill.id,
286+
title: skill.title,
287+
status: 'unknown',
288+
available: 0,
289+
total_sales: skill.total_sales,
290+
needs_restock: true,
291+
}
292+
}
293+
}))
294+
295+
const lowStock = results.filter(r => r.needs_restock)
296+
return {
297+
skills: results,
298+
total_skills: results.length,
299+
low_stock: lowStock.length,
300+
alerts: lowStock.map(s => `"${s.title}" has ${s.available} copies left.`),
301+
}
302+
}
303+
260304
export async function bountiesList(opts: ListOpts & { status?: string }) {
261305
let q = listParams(opts)
262306
if (opts.status) q += `&status=${encodeURIComponent(opts.status)}`

src/help.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const RESOURCES = ['skills', 'bounties', 'agents', 'escrows', 'wallets', 'config
66
type Resource = typeof RESOURCES[number]
77

88
const ACTIONS: Record<Resource, string[]> = {
9-
skills: ['list', 'show', 'vote', 'comment', 'create'],
9+
skills: ['list', 'show', 'vote', 'comment', 'create', 'sales'],
1010
bounties: ['list', 'show', 'create'],
1111
agents: ['list', 'show'],
1212
escrows: ['list', 'show', 'create', 'fund', 'commit-key', 'reveal-key', 'claim', 'status'],
@@ -619,6 +619,21 @@ Authentication:
619619
Examples:
620620
ade skills create --title "Data Analysis" --price 0.1`
621621

622+
case 'skills sales':
623+
return `ade skills sales - Check sales status and inventory
624+
625+
Usage:
626+
ade skills sales <seller_address>
627+
628+
Arguments:
629+
seller_address Ethereum address of the seller (0x...)
630+
631+
Shows available copies, total sales, and low-stock alerts for all
632+
active skills listed by the given seller address.
633+
634+
Examples:
635+
ade skills sales 0x1234...abcd`
636+
622637
case 'bounties list':
623638
return `ade bounties list - List bounties
624639

src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ async function handleResource(
174174
category: flags.category as string,
175175
});
176176
break;
177+
case "sales":
178+
if (!cmdArgs[0]) {
179+
console.error("Usage: ade skills sales <seller_address>");
180+
process.exit(1);
181+
}
182+
result = await commands.skillsSales(cmdArgs[0]);
183+
break;
177184
default:
178185
console.error(`Unknown action: skills ${action}`);
179186
process.exit(1);

0 commit comments

Comments
 (0)