@chainalert/cli 0.0.1
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/dist/alerts-STXD4TE5.js +134 -0
- package/dist/auth-6LTJFNU2.js +124 -0
- package/dist/channels-C5JZON37.js +179 -0
- package/dist/chunk-6FDEYAAT.js +27 -0
- package/dist/chunk-CE4DKHAY.js +28 -0
- package/dist/chunk-IC5RERFB.js +185 -0
- package/dist/chunk-K2BGDX7X.js +38 -0
- package/dist/chunk-WPW7UBVR.js +95 -0
- package/dist/contracts-J7JYPQXP.js +108 -0
- package/dist/detections-QSMNEXXI.js +282 -0
- package/dist/events-FM7VK5VH.js +104 -0
- package/dist/health-7R5HLRCZ.js +40 -0
- package/dist/index.js +159 -0
- package/dist/networks-CF2ARYQO.js +57 -0
- package/dist/org-contracts-DM2BTHTO.js +175 -0
- package/dist/repl-Q43IBAFT.js +1657 -0
- package/dist/rpc-configs-P2QCFCDJ.js +112 -0
- package/dist/state-changes-B6BIS4OJ.js +67 -0
- package/dist/templates-LYY2SV42.js +106 -0
- package/package.json +36 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/config/constants.ts
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
var VERSION = "0.0.1";
|
|
7
|
+
var DEFAULT_API_URL = "https://api.chainalert.dev";
|
|
8
|
+
var CONFIG_DIR = join(homedir(), ".chainalert");
|
|
9
|
+
var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
10
|
+
|
|
11
|
+
// src/util/output.ts
|
|
12
|
+
var RESET = "\x1B[0m";
|
|
13
|
+
var RED = "\x1B[31m";
|
|
14
|
+
var GREEN = "\x1B[32m";
|
|
15
|
+
var YELLOW = "\x1B[33m";
|
|
16
|
+
var CYAN = "\x1B[36m";
|
|
17
|
+
var DIM = "\x1B[2m";
|
|
18
|
+
var BOLD = "\x1B[1m";
|
|
19
|
+
function print(msg) {
|
|
20
|
+
process.stdout.write(msg + "\n");
|
|
21
|
+
}
|
|
22
|
+
function printError(msg) {
|
|
23
|
+
process.stderr.write(`${RED}Error: ${msg}${RESET}
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
function printSuccess(msg) {
|
|
27
|
+
print(`${GREEN}${msg}${RESET}`);
|
|
28
|
+
}
|
|
29
|
+
function printWarn(msg) {
|
|
30
|
+
print(`${YELLOW}${msg}${RESET}`);
|
|
31
|
+
}
|
|
32
|
+
function printDim(msg) {
|
|
33
|
+
print(`${DIM}${msg}${RESET}`);
|
|
34
|
+
}
|
|
35
|
+
function bold(s) {
|
|
36
|
+
return `${BOLD}${s}${RESET}`;
|
|
37
|
+
}
|
|
38
|
+
function cyan(s) {
|
|
39
|
+
return `${CYAN}${s}${RESET}`;
|
|
40
|
+
}
|
|
41
|
+
function dim(s) {
|
|
42
|
+
return `${DIM}${s}${RESET}`;
|
|
43
|
+
}
|
|
44
|
+
function green(s) {
|
|
45
|
+
return `${GREEN}${s}${RESET}`;
|
|
46
|
+
}
|
|
47
|
+
function red(s) {
|
|
48
|
+
return `${RED}${s}${RESET}`;
|
|
49
|
+
}
|
|
50
|
+
function yellow(s) {
|
|
51
|
+
return `${YELLOW}${s}${RESET}`;
|
|
52
|
+
}
|
|
53
|
+
function printTable(headers, rows) {
|
|
54
|
+
const widths = headers.map((h, i) => {
|
|
55
|
+
const colMax = rows.reduce((max, row) => Math.max(max, (row[i] ?? "").length), 0);
|
|
56
|
+
return Math.max(h.length, colMax);
|
|
57
|
+
});
|
|
58
|
+
const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(" ");
|
|
59
|
+
const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u2500");
|
|
60
|
+
print(`${BOLD}${headerLine}${RESET}`);
|
|
61
|
+
print(`${DIM}${separator}${RESET}`);
|
|
62
|
+
for (const row of rows) {
|
|
63
|
+
print(row.map((cell, i) => (cell ?? "").padEnd(widths[i])).join(" "));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function printKV(pairs) {
|
|
67
|
+
const maxKey = pairs.reduce((max, [k]) => Math.max(max, k.length), 0);
|
|
68
|
+
for (const [key, value] of pairs) {
|
|
69
|
+
print(`${BOLD}${key.padEnd(maxKey)}${RESET} ${value}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function printJson(data) {
|
|
73
|
+
print(JSON.stringify(data, null, 2));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
VERSION,
|
|
78
|
+
DEFAULT_API_URL,
|
|
79
|
+
CONFIG_DIR,
|
|
80
|
+
CONFIG_FILE,
|
|
81
|
+
print,
|
|
82
|
+
printError,
|
|
83
|
+
printSuccess,
|
|
84
|
+
printWarn,
|
|
85
|
+
printDim,
|
|
86
|
+
bold,
|
|
87
|
+
cyan,
|
|
88
|
+
dim,
|
|
89
|
+
green,
|
|
90
|
+
red,
|
|
91
|
+
yellow,
|
|
92
|
+
printTable,
|
|
93
|
+
printKV,
|
|
94
|
+
printJson
|
|
95
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
spinner
|
|
4
|
+
} from "./chunk-CE4DKHAY.js";
|
|
5
|
+
import {
|
|
6
|
+
getStorageSlots,
|
|
7
|
+
resolveContract
|
|
8
|
+
} from "./chunk-IC5RERFB.js";
|
|
9
|
+
import "./chunk-K2BGDX7X.js";
|
|
10
|
+
import {
|
|
11
|
+
bold,
|
|
12
|
+
dim,
|
|
13
|
+
print,
|
|
14
|
+
printError,
|
|
15
|
+
printJson,
|
|
16
|
+
printKV
|
|
17
|
+
} from "./chunk-WPW7UBVR.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/contracts.ts
|
|
20
|
+
async function run(args, flags) {
|
|
21
|
+
const sub = args[0];
|
|
22
|
+
switch (sub) {
|
|
23
|
+
case "resolve": {
|
|
24
|
+
if (!flags.address) {
|
|
25
|
+
printError("--address is required.");
|
|
26
|
+
process.exitCode = 1;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!flags.network) {
|
|
30
|
+
printError("--network is required.");
|
|
31
|
+
process.exitCode = 1;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
spinner.start("Resolving contract...");
|
|
36
|
+
const result = await resolveContract({
|
|
37
|
+
address: flags.address,
|
|
38
|
+
networkId: flags.network
|
|
39
|
+
});
|
|
40
|
+
spinner.stop();
|
|
41
|
+
if (flags.json) {
|
|
42
|
+
printJson(result);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const c = result.data;
|
|
46
|
+
printKV([
|
|
47
|
+
["Address", c.address ?? flags.address],
|
|
48
|
+
["Network", c.networkId ?? flags.network],
|
|
49
|
+
["Name", c.name ?? dim("(unknown)")],
|
|
50
|
+
["Verified", c.verified !== void 0 ? String(c.verified) : dim("(unknown)")],
|
|
51
|
+
["Proxy", c.isProxy !== void 0 ? String(c.isProxy) : dim("(unknown)")]
|
|
52
|
+
]);
|
|
53
|
+
if (c.abi) {
|
|
54
|
+
print("");
|
|
55
|
+
print(bold("ABI:") + ` ${Array.isArray(c.abi) ? `${c.abi.length} entries` : "available"}`);
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
spinner.stop();
|
|
59
|
+
printError(err.message ?? "Failed to resolve contract.");
|
|
60
|
+
process.exitCode = 1;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case "storage-slots": {
|
|
65
|
+
const id = args[1];
|
|
66
|
+
if (!id) {
|
|
67
|
+
printError("Usage: chainalert contracts storage-slots <id>");
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
spinner.start("Fetching storage slots...");
|
|
73
|
+
const result = await getStorageSlots(id);
|
|
74
|
+
spinner.stop();
|
|
75
|
+
if (flags.json) {
|
|
76
|
+
printJson(result);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const slots = result.data;
|
|
80
|
+
if (Array.isArray(slots) && slots.length > 0) {
|
|
81
|
+
for (const slot of slots) {
|
|
82
|
+
printKV([
|
|
83
|
+
["Slot", slot.slot ?? slot.key ?? ""],
|
|
84
|
+
["Label", slot.label ?? slot.name ?? dim("(unnamed)")],
|
|
85
|
+
["Type", slot.type ?? dim("(unknown)")]
|
|
86
|
+
]);
|
|
87
|
+
print("");
|
|
88
|
+
}
|
|
89
|
+
} else if (slots && typeof slots === "object") {
|
|
90
|
+
print(JSON.stringify(slots, null, 2));
|
|
91
|
+
} else {
|
|
92
|
+
print("No storage slots found.");
|
|
93
|
+
}
|
|
94
|
+
} catch (err) {
|
|
95
|
+
spinner.stop();
|
|
96
|
+
printError(err.message ?? "Failed to fetch storage slots.");
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
printError(`Unknown subcommand: ${sub ?? "(none)"}. Use: resolve, storage-slots`);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export {
|
|
107
|
+
run
|
|
108
|
+
};
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
confirm
|
|
4
|
+
} from "./chunk-6FDEYAAT.js";
|
|
5
|
+
import {
|
|
6
|
+
spinner
|
|
7
|
+
} from "./chunk-CE4DKHAY.js";
|
|
8
|
+
import {
|
|
9
|
+
createDetection,
|
|
10
|
+
deleteDetection,
|
|
11
|
+
getDetection,
|
|
12
|
+
listDetections,
|
|
13
|
+
testDetection,
|
|
14
|
+
updateDetection
|
|
15
|
+
} from "./chunk-IC5RERFB.js";
|
|
16
|
+
import "./chunk-K2BGDX7X.js";
|
|
17
|
+
import {
|
|
18
|
+
bold,
|
|
19
|
+
dim,
|
|
20
|
+
green,
|
|
21
|
+
print,
|
|
22
|
+
printError,
|
|
23
|
+
printJson,
|
|
24
|
+
printKV,
|
|
25
|
+
printSuccess,
|
|
26
|
+
printTable,
|
|
27
|
+
red,
|
|
28
|
+
yellow
|
|
29
|
+
} from "./chunk-WPW7UBVR.js";
|
|
30
|
+
|
|
31
|
+
// src/commands/detections.ts
|
|
32
|
+
async function run(args, flags) {
|
|
33
|
+
const sub = args[0] ?? "list";
|
|
34
|
+
switch (sub) {
|
|
35
|
+
case "list": {
|
|
36
|
+
try {
|
|
37
|
+
spinner.start("Fetching detections...");
|
|
38
|
+
const result = await listDetections({
|
|
39
|
+
status: flags.status,
|
|
40
|
+
networkId: flags.network,
|
|
41
|
+
page: flags.page ? Number(flags.page) : void 0,
|
|
42
|
+
limit: flags.limit ? Number(flags.limit) : void 0
|
|
43
|
+
});
|
|
44
|
+
spinner.stop();
|
|
45
|
+
if (flags.json) {
|
|
46
|
+
printJson(result);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!result.data.length) {
|
|
50
|
+
print("No detections found.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
printTable(
|
|
54
|
+
["ID", "Name", "Template", "Network", "Status"],
|
|
55
|
+
result.data.map((d) => [
|
|
56
|
+
String(d.id),
|
|
57
|
+
d.name ?? "",
|
|
58
|
+
d.templateSlug ?? "",
|
|
59
|
+
d.networkSlug ?? d.networkId ?? "",
|
|
60
|
+
d.status ?? ""
|
|
61
|
+
])
|
|
62
|
+
);
|
|
63
|
+
if (result.meta) {
|
|
64
|
+
print(dim(`
|
|
65
|
+
Page ${result.meta.page ?? 1} of ${result.meta.totalPages ?? "?"} (${result.meta.total ?? "?"} total)`));
|
|
66
|
+
}
|
|
67
|
+
} catch (err) {
|
|
68
|
+
spinner.stop();
|
|
69
|
+
printError(err.message ?? "Failed to fetch detections.");
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case "get": {
|
|
75
|
+
const id = args[1];
|
|
76
|
+
if (!id) {
|
|
77
|
+
printError("Usage: chainalert detections get <id>");
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
spinner.start("Fetching detection...");
|
|
83
|
+
const result = await getDetection(id);
|
|
84
|
+
spinner.stop();
|
|
85
|
+
if (flags.json) {
|
|
86
|
+
printJson(result);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const d = result.data;
|
|
90
|
+
printKV([
|
|
91
|
+
["ID", String(d.id)],
|
|
92
|
+
["Name", d.name ?? ""],
|
|
93
|
+
["Template", d.templateSlug ?? ""],
|
|
94
|
+
["Network", d.networkSlug ?? d.networkId ?? ""],
|
|
95
|
+
["Contract", d.contractAddress ?? dim("(none)")],
|
|
96
|
+
["Status", d.status ?? ""],
|
|
97
|
+
["Severity", d.severity ?? ""],
|
|
98
|
+
["Cooldown", d.cooldownMinutes ? `${d.cooldownMinutes} min` : dim("(default)")],
|
|
99
|
+
["Created", d.createdAt ?? ""]
|
|
100
|
+
]);
|
|
101
|
+
if (d.inputs && Object.keys(d.inputs).length > 0) {
|
|
102
|
+
print("");
|
|
103
|
+
print(bold("Inputs:"));
|
|
104
|
+
for (const [key, value] of Object.entries(d.inputs)) {
|
|
105
|
+
print(` ${bold(key)}: ${String(value)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (d.channelIds && d.channelIds.length > 0) {
|
|
109
|
+
print("");
|
|
110
|
+
print(bold("Channels:") + " " + d.channelIds.join(", "));
|
|
111
|
+
}
|
|
112
|
+
} catch (err) {
|
|
113
|
+
spinner.stop();
|
|
114
|
+
printError(err.message ?? "Failed to fetch detection.");
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case "create": {
|
|
120
|
+
if (!flags.template) {
|
|
121
|
+
printError("--template is required.");
|
|
122
|
+
process.exitCode = 1;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!flags.name) {
|
|
126
|
+
printError("--name is required.");
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (!flags.network) {
|
|
131
|
+
printError("--network is required.");
|
|
132
|
+
process.exitCode = 1;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const inputs = {};
|
|
136
|
+
for (const [key, value] of Object.entries(flags)) {
|
|
137
|
+
if (key.startsWith("input.")) {
|
|
138
|
+
inputs[key.slice(6)] = value;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const channelIds = flags.channel ? flags.channel.split(",").map((s) => s.trim()) : void 0;
|
|
142
|
+
try {
|
|
143
|
+
spinner.start("Creating detection...");
|
|
144
|
+
const result = await createDetection({
|
|
145
|
+
templateSlug: flags.template,
|
|
146
|
+
name: flags.name,
|
|
147
|
+
networkId: flags.network,
|
|
148
|
+
contractAddress: flags.contract,
|
|
149
|
+
inputs,
|
|
150
|
+
channelIds,
|
|
151
|
+
severity: flags.severity,
|
|
152
|
+
cooldownMinutes: flags.cooldown ? Number(flags.cooldown) : void 0,
|
|
153
|
+
testBlockNumber: flags.block ? Number(flags.block) : void 0
|
|
154
|
+
});
|
|
155
|
+
spinner.stop();
|
|
156
|
+
if (flags.json) {
|
|
157
|
+
printJson(result);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
printSuccess(`Detection created: ${result.data.id}`);
|
|
161
|
+
if (result.testPassed !== void 0) {
|
|
162
|
+
if (result.testPassed) {
|
|
163
|
+
print(green("Test passed."));
|
|
164
|
+
} else {
|
|
165
|
+
print(yellow("Test did not pass."));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
spinner.stop();
|
|
170
|
+
printError(err.message ?? "Failed to create detection.");
|
|
171
|
+
process.exitCode = 1;
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case "update": {
|
|
176
|
+
const id = args[1];
|
|
177
|
+
if (!id) {
|
|
178
|
+
printError("Usage: chainalert detections update <id> [--name] [--status]");
|
|
179
|
+
process.exitCode = 1;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const body = {};
|
|
183
|
+
if (flags.name) body.name = flags.name;
|
|
184
|
+
if (flags.status) body.status = flags.status;
|
|
185
|
+
const inputs = {};
|
|
186
|
+
for (const [key, value] of Object.entries(flags)) {
|
|
187
|
+
if (key.startsWith("input.")) {
|
|
188
|
+
inputs[key.slice(6)] = value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (Object.keys(inputs).length > 0) body.inputs = inputs;
|
|
192
|
+
if (flags.channel) body.channelIds = flags.channel.split(",").map((s) => s.trim());
|
|
193
|
+
if (flags.cooldown) body.cooldownMinutes = Number(flags.cooldown);
|
|
194
|
+
try {
|
|
195
|
+
spinner.start("Updating detection...");
|
|
196
|
+
const result = await updateDetection(id, body);
|
|
197
|
+
spinner.stop();
|
|
198
|
+
if (flags.json) {
|
|
199
|
+
printJson(result);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
printSuccess(`Detection ${id} updated.`);
|
|
203
|
+
} catch (err) {
|
|
204
|
+
spinner.stop();
|
|
205
|
+
printError(err.message ?? "Failed to update detection.");
|
|
206
|
+
process.exitCode = 1;
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
case "delete": {
|
|
211
|
+
const id = args[1];
|
|
212
|
+
if (!id) {
|
|
213
|
+
printError("Usage: chainalert detections delete <id>");
|
|
214
|
+
process.exitCode = 1;
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const ok = await confirm(`Delete detection ${id}?`);
|
|
218
|
+
if (!ok) {
|
|
219
|
+
print("Cancelled.");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
spinner.start("Deleting detection...");
|
|
224
|
+
const result = await deleteDetection(id);
|
|
225
|
+
spinner.stop();
|
|
226
|
+
if (flags.json) {
|
|
227
|
+
printJson(result);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
printSuccess(`Detection ${id} deleted.`);
|
|
231
|
+
} catch (err) {
|
|
232
|
+
spinner.stop();
|
|
233
|
+
printError(err.message ?? "Failed to delete detection.");
|
|
234
|
+
process.exitCode = 1;
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case "test": {
|
|
239
|
+
const id = args[1];
|
|
240
|
+
if (!id) {
|
|
241
|
+
printError("Usage: chainalert detections test <id> --block=<number>");
|
|
242
|
+
process.exitCode = 1;
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!flags.block) {
|
|
246
|
+
printError("--block is required.");
|
|
247
|
+
process.exitCode = 1;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
spinner.start("Testing detection...");
|
|
252
|
+
const result = await testDetection(id, { blockNumber: Number(flags.block) });
|
|
253
|
+
spinner.stop();
|
|
254
|
+
if (flags.json) {
|
|
255
|
+
printJson(result);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (result.testPassed) {
|
|
259
|
+
printSuccess("Test passed.");
|
|
260
|
+
} else {
|
|
261
|
+
print(red("Test did not pass."));
|
|
262
|
+
}
|
|
263
|
+
if (result.testResult) {
|
|
264
|
+
print("");
|
|
265
|
+
print(bold("Result:"));
|
|
266
|
+
print(JSON.stringify(result.testResult, null, 2));
|
|
267
|
+
}
|
|
268
|
+
} catch (err) {
|
|
269
|
+
spinner.stop();
|
|
270
|
+
printError(err.message ?? "Failed to test detection.");
|
|
271
|
+
process.exitCode = 1;
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
default:
|
|
276
|
+
printError(`Unknown subcommand: ${sub}. Use: list, get, create, update, delete, test`);
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
export {
|
|
281
|
+
run
|
|
282
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
spinner
|
|
4
|
+
} from "./chunk-CE4DKHAY.js";
|
|
5
|
+
import {
|
|
6
|
+
getEvent,
|
|
7
|
+
listEvents
|
|
8
|
+
} from "./chunk-IC5RERFB.js";
|
|
9
|
+
import "./chunk-K2BGDX7X.js";
|
|
10
|
+
import {
|
|
11
|
+
dim,
|
|
12
|
+
print,
|
|
13
|
+
printError,
|
|
14
|
+
printJson,
|
|
15
|
+
printKV,
|
|
16
|
+
printTable
|
|
17
|
+
} from "./chunk-WPW7UBVR.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/events.ts
|
|
20
|
+
async function run(args, flags) {
|
|
21
|
+
const sub = args[0] ?? "list";
|
|
22
|
+
switch (sub) {
|
|
23
|
+
case "list": {
|
|
24
|
+
try {
|
|
25
|
+
spinner.start("Fetching events...");
|
|
26
|
+
const result = await listEvents({
|
|
27
|
+
detectionId: flags.detection,
|
|
28
|
+
page: flags.page ? Number(flags.page) : void 0,
|
|
29
|
+
limit: flags.limit ? Number(flags.limit) : void 0
|
|
30
|
+
});
|
|
31
|
+
spinner.stop();
|
|
32
|
+
if (flags.json) {
|
|
33
|
+
printJson(result);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!result.data.length) {
|
|
37
|
+
print("No events found.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
printTable(
|
|
41
|
+
["ID", "Detection", "Event Name", "Block", "Tx Hash"],
|
|
42
|
+
result.data.map((e) => [
|
|
43
|
+
String(e.id),
|
|
44
|
+
e.detectionId ?? "",
|
|
45
|
+
e.eventName ?? "",
|
|
46
|
+
e.blockNumber ? String(e.blockNumber) : "",
|
|
47
|
+
e.txHash ?? ""
|
|
48
|
+
])
|
|
49
|
+
);
|
|
50
|
+
if (result.meta) {
|
|
51
|
+
print(dim(`
|
|
52
|
+
Page ${result.meta.page ?? 1} of ${result.meta.totalPages ?? "?"} (${result.meta.total ?? "?"} total)`));
|
|
53
|
+
}
|
|
54
|
+
} catch (err) {
|
|
55
|
+
spinner.stop();
|
|
56
|
+
printError(err.message ?? "Failed to fetch events.");
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case "get": {
|
|
62
|
+
const id = args[1];
|
|
63
|
+
if (!id) {
|
|
64
|
+
printError("Usage: chainalert events get <id>");
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
spinner.start("Fetching event...");
|
|
70
|
+
const result = await getEvent(id);
|
|
71
|
+
spinner.stop();
|
|
72
|
+
if (flags.json) {
|
|
73
|
+
printJson(result);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const e = result.data;
|
|
77
|
+
printKV([
|
|
78
|
+
["ID", String(e.id)],
|
|
79
|
+
["Detection", e.detectionId ?? ""],
|
|
80
|
+
["Event Name", e.eventName ?? ""],
|
|
81
|
+
["Block", e.blockNumber ? String(e.blockNumber) : dim("(n/a)")],
|
|
82
|
+
["Tx Hash", e.txHash ?? dim("(n/a)")],
|
|
83
|
+
["Log Index", e.logIndex !== void 0 ? String(e.logIndex) : dim("(n/a)")],
|
|
84
|
+
["Created", e.createdAt ?? ""]
|
|
85
|
+
]);
|
|
86
|
+
if (e.args || e.data) {
|
|
87
|
+
print("");
|
|
88
|
+
print(JSON.stringify(e.args ?? e.data, null, 2));
|
|
89
|
+
}
|
|
90
|
+
} catch (err) {
|
|
91
|
+
spinner.stop();
|
|
92
|
+
printError(err.message ?? "Failed to fetch event.");
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
default:
|
|
98
|
+
printError(`Unknown subcommand: ${sub}. Use: list, get`);
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
run
|
|
104
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
spinner
|
|
4
|
+
} from "./chunk-CE4DKHAY.js";
|
|
5
|
+
import {
|
|
6
|
+
getHealth
|
|
7
|
+
} from "./chunk-IC5RERFB.js";
|
|
8
|
+
import "./chunk-K2BGDX7X.js";
|
|
9
|
+
import {
|
|
10
|
+
print,
|
|
11
|
+
printError,
|
|
12
|
+
printJson,
|
|
13
|
+
printSuccess,
|
|
14
|
+
red
|
|
15
|
+
} from "./chunk-WPW7UBVR.js";
|
|
16
|
+
|
|
17
|
+
// src/commands/health.ts
|
|
18
|
+
async function run(args, flags) {
|
|
19
|
+
try {
|
|
20
|
+
spinner.start("Checking API health...");
|
|
21
|
+
const result = await getHealth();
|
|
22
|
+
spinner.stop();
|
|
23
|
+
if (flags.json) {
|
|
24
|
+
printJson(result);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (result.status === "ok") {
|
|
28
|
+
printSuccess("API is healthy.");
|
|
29
|
+
} else {
|
|
30
|
+
print(`Status: ${red(result.status)}`);
|
|
31
|
+
}
|
|
32
|
+
} catch (err) {
|
|
33
|
+
spinner.stop();
|
|
34
|
+
printError(err.message ?? "Failed to reach API.");
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
run
|
|
40
|
+
};
|