@inversealtruism/cairn-cli 0.1.0 → 0.2.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 +5 -0
- package/dist/cli.js +106 -0
- package/dist/lib/api.js +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,6 +41,11 @@ cairn watch # live auto-refreshing board
|
|
|
41
41
|
cairn recent # recent proposals and support
|
|
42
42
|
cairn show <id> # item detail and integrity check
|
|
43
43
|
cairn verify <id> # recompute the content hash and check it
|
|
44
|
+
cairn wall # the Wall — top stones + the reigning King
|
|
45
|
+
cairn network # live network telemetry (alias: cairn stats)
|
|
46
|
+
cairn quests # open quests
|
|
47
|
+
cairn profile <addr> # identity + on-chain reputation
|
|
48
|
+
cairn leaderboard # top builders by reputation
|
|
44
49
|
cairn ls --json # machine-readable output
|
|
45
50
|
```
|
|
46
51
|
|
package/dist/cli.js
CHANGED
|
@@ -205,6 +205,100 @@ async function cmdDomains() {
|
|
|
205
205
|
console.log(` ${c.cyan(pad(d.key, 20))} ${c.gray((d.count != null ? d.count + " items" : "") + (d.totalWeight ? " · " + csdToCoins(d.totalWeight) + " CSD" : ""))}`);
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
+
async function cmdWall() {
|
|
209
|
+
const r = await api.apiWall();
|
|
210
|
+
const stones = r.stones ?? [];
|
|
211
|
+
banner();
|
|
212
|
+
rule(`the wall · ${r.totals?.stones ?? 0} stones · ${r.totals?.boosts ?? 0} boosts · epoch ${r.epoch ?? "?"}`);
|
|
213
|
+
if (r.king)
|
|
214
|
+
console.log(` ${c.green("★ KING")} ${c.white(c.bold(r.king.message))} ${csdFmt(r.king.weight)} ${c.gray("· " + r.king.boosts + " boosts")}`);
|
|
215
|
+
if (!stones.length) {
|
|
216
|
+
console.log(c.gray("\n no stones yet — place one with the Cairn Wallet, or:"));
|
|
217
|
+
console.log(c.green(" cairn propose --domain cairn:wall --title '<message>'"));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const max = stones[0]?.weight || 1;
|
|
221
|
+
stones.slice(0, 25).forEach((s, i) => {
|
|
222
|
+
console.log("");
|
|
223
|
+
console.log(` ${c.magenta(c.bold("#" + (i + 1)))} ${c.white(c.bold(s.message))}${i === 0 ? " " + c.green("★") : ""}`);
|
|
224
|
+
console.log(` ${bar(s.weight, max)} ${csdFmt(s.weight)} ${c.gray("·")} ${c.green(String(s.boosts))} ${c.gray("boosts · " + age(s.ts) + " ago")}${(s.tags && s.tags.length) ? c.gray(" #" + s.tags.join(" #")) : ""}`);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
async function cmdNetwork() {
|
|
228
|
+
const [n, s] = await Promise.all([api.apiNetwork(), api.apiStats().catch(() => null)]);
|
|
229
|
+
banner();
|
|
230
|
+
rule("network · compute substrate");
|
|
231
|
+
if (!n || !n.reachable) {
|
|
232
|
+
console.log(err("node unreachable"));
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const row = (k, v) => console.log(` ${kdim(pad(k, 15))} ${v}`);
|
|
236
|
+
const hr = (g) => (g >= 1000 ? (g / 1000).toFixed(2) + " TH/s" : (g ?? 0).toFixed(1) + " GH/s");
|
|
237
|
+
row("hashrate", `${c.white(hr(n.hashrateGHs))} ${c.gray("(1h " + hr(n.hashrate1h) + " · 24h " + hr(n.hashrate24h) + ")")}`);
|
|
238
|
+
row("block height", `${c.white(String(n.height))} ${c.gray("· last block " + age(n.lastBlockTime) + " ago")}`);
|
|
239
|
+
row("block time", `${c.white((n.avgBlockTimeSecs ?? 0).toFixed(0) + "s")} ${c.gray("(target " + n.targetBlockSecs + "s)")}`);
|
|
240
|
+
row("miners", `${c.white(String(n.minerCount))} ${c.gray("active ~24h")}`);
|
|
241
|
+
row("peers", `${c.white(String(n.peers))} ${c.gray("connected · " + n.knownPeers + " known · mempool " + n.mempoolTxCount)}`);
|
|
242
|
+
row("block reward", `${c.white(n.blockRewardCoins + " CSD")} ${c.gray("· " + Math.round(n.emittedSupplyCoins).toLocaleString() + " CSD emitted")}`);
|
|
243
|
+
row("chain age", c.white((n.chainAgeDays ?? 0).toFixed(1) + " days"));
|
|
244
|
+
row("activity", `${c.green(String(n.proposals))} proposals ${c.gray("·")} ${c.green(String(n.attestations))} attestations ${c.gray("· " + Number(n.transactions).toLocaleString() + " txs")}`);
|
|
245
|
+
if (s)
|
|
246
|
+
row("board", `${c.green(String(s.items))} items ${c.gray("·")} ${c.green(String(s.supports))} supports ${c.gray("·")} ${c.green(String(s.participants))} participants ${c.gray("· " + s.totalSignalCoins + " CSD signal")}`);
|
|
247
|
+
}
|
|
248
|
+
async function cmdProfile(a) {
|
|
249
|
+
const addr = a._[1];
|
|
250
|
+
if (!addr) {
|
|
251
|
+
console.log(warn("usage: ") + c.cyan("cairn profile <addr>"));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const r = await api.apiProfile(addr).catch(() => null);
|
|
255
|
+
if (!r || !r.ok) {
|
|
256
|
+
console.log(err("no profile for " + addr));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const p = r.profile || {}, rep = r.reputation || {};
|
|
260
|
+
banner();
|
|
261
|
+
rule(`profile · ${p.handle || addr}`);
|
|
262
|
+
if (p.handle)
|
|
263
|
+
console.log(` ${kdim(pad("handle", 13))} ${c.white(p.handle)}`);
|
|
264
|
+
if (p.bio)
|
|
265
|
+
console.log(` ${kdim(pad("bio", 13))} ${c.gray(p.bio)}`);
|
|
266
|
+
if (p.github)
|
|
267
|
+
console.log(` ${kdim(pad("github", 13))} ${c.cyan(p.github)} ${p.githubVerified ? ok("verified") : c.gray("(unverified)")}`);
|
|
268
|
+
console.log(` ${kdim(pad("address", 13))} ${c.gray(p.addr || addr)}`);
|
|
269
|
+
console.log(` ${kdim(pad("trust", 13))} ${c.white((rep.trust ?? 0).toFixed(2))}`);
|
|
270
|
+
console.log(` ${kdim(pad("work", 13))} ${c.green(String(rep.proposed ?? 0))} proposed ${c.gray("·")} ${c.green(String(rep.shipped ?? 0))} shipped ${c.gray("·")} ${c.green(String(rep.acceptedWork ?? 0))} accepted ${c.gray("·")} ${c.green(String(rep.reviews ?? 0))} reviews`);
|
|
271
|
+
}
|
|
272
|
+
async function cmdLeaderboard() {
|
|
273
|
+
const r = await api.apiLeaderboard();
|
|
274
|
+
banner();
|
|
275
|
+
rule("reputation leaderboard");
|
|
276
|
+
const lb = r.leaderboard ?? [];
|
|
277
|
+
if (!lb.length) {
|
|
278
|
+
console.log(c.gray(" no ranked builders yet — reputation accrues from accepted quest work."));
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
lb.slice(0, 25).forEach((e, i) => {
|
|
282
|
+
console.log(` ${c.magenta(c.bold(pad("#" + (i + 1), 4)))} ${c.white(pad(e.handle || e.addr, 26))} ${c.gray("trust")} ${c.white((e.trust ?? 0).toFixed(2))} ${c.gray("· " + (e.shipped ?? e.acceptedWork ?? 0) + " shipped · " + (e.proposed ?? 0) + " proposed")}`);
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
async function cmdQuests() {
|
|
286
|
+
const r = await api.apiQuests();
|
|
287
|
+
banner();
|
|
288
|
+
rule("quests");
|
|
289
|
+
const qs = r.quests ?? [];
|
|
290
|
+
if (!qs.length) {
|
|
291
|
+
console.log(c.gray(" no open quests yet."));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
qs.slice(0, 25).forEach((q, i) => {
|
|
295
|
+
const reward = q.quest?.reward?.build ? csdToCoins(q.quest.reward.build) + " CSD" : "—";
|
|
296
|
+
console.log("");
|
|
297
|
+
console.log(` ${c.magenta(c.bold("#" + (i + 1)))} ${c.white(c.bold(q.title))} ${c.gray("· " + (q.status || "?"))}`);
|
|
298
|
+
console.log(` ${c.gray("reward " + reward + " · demand " + csdFmt(q.demandWeight || 0) + " · " + (q.demandSupporters || 0) + " backers")}`);
|
|
299
|
+
console.log(c.gray(` id ${String(q.id).slice(0, 22)}…`));
|
|
300
|
+
});
|
|
301
|
+
}
|
|
208
302
|
async function help() {
|
|
209
303
|
await bannerAnimated();
|
|
210
304
|
const cmd = (n, args, d) => console.log(` ${c.cyan(pad(n, 9))} ${c.gray(pad(args, 44))} ${c.dim(d)}`);
|
|
@@ -216,6 +310,11 @@ async function help() {
|
|
|
216
310
|
cmd("recent", "", "recent proposals + support");
|
|
217
311
|
cmd("show", "<id>", "item detail + integrity");
|
|
218
312
|
cmd("verify", "<id>", "recompute hash, check vs chain");
|
|
313
|
+
cmd("wall", "", "the Wall — top stones + King");
|
|
314
|
+
cmd("network", "", "live network telemetry (alias: stats)");
|
|
315
|
+
cmd("quests", "", "open quests");
|
|
316
|
+
cmd("profile", "<addr>", "identity + reputation");
|
|
317
|
+
cmd("leaderboard", "", "top builders by reputation");
|
|
219
318
|
cmd("propose", "--domain <d> --title <t> --body <b>", "post an item (needs CAIRN_TOKEN)");
|
|
220
319
|
cmd("support", "<id> --fee <base>", "back an item (needs CAIRN_TOKEN)");
|
|
221
320
|
console.log(c.gray("\n lenses (--sort): " + Object.keys(LENS).join(" · ")));
|
|
@@ -235,6 +334,13 @@ async function main() {
|
|
|
235
334
|
case "recent": return cmdRecent();
|
|
236
335
|
case "show": return cmdShow(a);
|
|
237
336
|
case "verify": return cmdVerify(a);
|
|
337
|
+
case "wall": return cmdWall();
|
|
338
|
+
case "network":
|
|
339
|
+
case "stats": return cmdNetwork();
|
|
340
|
+
case "quests": return cmdQuests();
|
|
341
|
+
case "profile": return cmdProfile(a);
|
|
342
|
+
case "leaderboard":
|
|
343
|
+
case "lb": return cmdLeaderboard();
|
|
238
344
|
case "propose": return cmdPropose(a);
|
|
239
345
|
case "support": return cmdSupport(a);
|
|
240
346
|
default: return help();
|
package/dist/lib/api.js
CHANGED
|
@@ -29,6 +29,11 @@ export const apiStats = () => req("/api/stats");
|
|
|
29
29
|
export const apiBoard = (domain, window) => req(`/api/board?domain=${encodeURIComponent(domain)}&window=${encodeURIComponent(window)}`);
|
|
30
30
|
export const apiItem = (id) => req(`/api/item/${encodeURIComponent(id)}`);
|
|
31
31
|
export const apiActivity = () => req("/api/activity");
|
|
32
|
+
export const apiWall = () => req("/api/wall");
|
|
33
|
+
export const apiNetwork = () => req("/api/network");
|
|
34
|
+
export const apiProfile = (addr) => req(`/api/profile/${encodeURIComponent(addr)}`);
|
|
35
|
+
export const apiLeaderboard = () => req("/api/leaderboard");
|
|
36
|
+
export const apiQuests = () => req("/api/quests");
|
|
32
37
|
export const apiPropose = (body) => writeReq("/api/propose", body);
|
|
33
38
|
export const apiSupport = (body) => writeReq("/api/support", body);
|
|
34
39
|
// optional: query a raw csd node RPC (for trustless verify)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inversealtruism/cairn-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Command-line client for a Cairn signal board on Compute Substrate — browse, propose, and back what to build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": { "cairn": "dist/cli.js" },
|