brainblast 0.6.3 → 0.7.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/dist/batchScan-JR2G5JCF.js +14 -0
- package/dist/chunk-2UZGWXIX.js +77 -0
- package/dist/chunk-2XJORJPQ.js +31 -0
- package/dist/{chunk-ZZ6LBZV5.js → chunk-34VXOLJF.js} +32 -433
- package/dist/{chunk-A56IF3UX.js → chunk-CRYFCQYM.js} +145 -19
- package/dist/chunk-DQ4KAYKQ.js +111 -0
- package/dist/chunk-FQA5BYWW.js +89 -0
- package/dist/chunk-HL7NVANZ.js +331 -0
- package/dist/chunk-O5Z4ZJHC.js +89 -0
- package/dist/chunk-QC27GNQ7.js +101 -0
- package/dist/chunk-SVSVVW6U.js +187 -0
- package/dist/chunk-UWE6HAGS.js +176 -0
- package/dist/chunk-VG5FMOLW.js +61 -0
- package/dist/chunk-VI2JBH2T.js +79 -0
- package/dist/chunk-WX3IR7LK.js +148 -0
- package/dist/chunk-XSVQSK53.js +100 -0
- package/dist/cli.js +321 -10
- package/dist/firewall-HN5XJLGC.js +18 -0
- package/dist/idlRules-3KZML4NL.js +17 -0
- package/dist/index.d.ts +307 -1
- package/dist/index.js +115 -22
- package/dist/{mcp-AFYJQ7K6.js → mcp-ML2X44WE.js} +3 -1
- package/dist/pumpCheck-K2ESOBNU.js +16 -0
- package/dist/ricomaps-WTMWBBOY.js +11 -0
- package/dist/rpc-W5F4KXS2.js +18 -0
- package/dist/rules/solana-token-impersonation.yaml +17 -0
- package/dist/score-VLKER37D.js +18 -0
- package/dist/tokenRegistry-CYIUZHAZ.js +8 -0
- package/dist/trustGraph-4SSJOQKT.js +49 -0
- package/dist/watchChain-F6INXAPA.js +13 -0
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -2,27 +2,36 @@
|
|
|
2
2
|
import {
|
|
3
3
|
analyzeCosts,
|
|
4
4
|
applyDiffToFile,
|
|
5
|
-
buildTrustGraph,
|
|
6
|
-
cacheSize,
|
|
7
|
-
defaultCachePath,
|
|
8
5
|
initPack,
|
|
9
6
|
isTelemetryEnabled,
|
|
10
|
-
isValidSolanaAddress,
|
|
11
|
-
loadProgramCache,
|
|
12
7
|
parseDiff,
|
|
13
8
|
recordGraduationEvents,
|
|
14
9
|
renderCostReportMd,
|
|
15
|
-
renderTrustGraphMd,
|
|
16
10
|
startWatch,
|
|
17
11
|
submitTelemetry,
|
|
18
12
|
telemetryFilePath,
|
|
19
13
|
validatePack
|
|
20
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-34VXOLJF.js";
|
|
15
|
+
import {
|
|
16
|
+
renderTrustGraphMd
|
|
17
|
+
} from "./chunk-2UZGWXIX.js";
|
|
18
|
+
import {
|
|
19
|
+
buildTrustGraph,
|
|
20
|
+
cacheSize,
|
|
21
|
+
defaultCachePath,
|
|
22
|
+
loadProgramCache
|
|
23
|
+
} from "./chunk-SVSVVW6U.js";
|
|
21
24
|
import {
|
|
22
25
|
audit,
|
|
23
26
|
getChangedRanges,
|
|
24
27
|
resolveRules
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-CRYFCQYM.js";
|
|
29
|
+
import "./chunk-2XJORJPQ.js";
|
|
30
|
+
import "./chunk-O5Z4ZJHC.js";
|
|
31
|
+
import "./chunk-XSVQSK53.js";
|
|
32
|
+
import {
|
|
33
|
+
isValidSolanaAddress
|
|
34
|
+
} from "./chunk-VG5FMOLW.js";
|
|
26
35
|
import "./chunk-3RG5ZIWI.js";
|
|
27
36
|
|
|
28
37
|
// src/cli.ts
|
|
@@ -119,7 +128,7 @@ if (args[0] === "drift") {
|
|
|
119
128
|
process.exit(0);
|
|
120
129
|
}
|
|
121
130
|
if (args[0] === "mcp") {
|
|
122
|
-
const { startMcpServer } = await import("./mcp-
|
|
131
|
+
const { startMcpServer } = await import("./mcp-ML2X44WE.js");
|
|
123
132
|
await startMcpServer();
|
|
124
133
|
process.exit(0);
|
|
125
134
|
}
|
|
@@ -143,6 +152,57 @@ if (args[0] === "watch") {
|
|
|
143
152
|
await new Promise(() => {
|
|
144
153
|
});
|
|
145
154
|
}
|
|
155
|
+
if (args[0] === "watch-chain") {
|
|
156
|
+
const rest = args.slice(1);
|
|
157
|
+
const programId = rest.find((a) => !a.startsWith("--"));
|
|
158
|
+
if (!programId) {
|
|
159
|
+
console.error("usage: brainblast watch-chain <program-id> [--rpc URL] [--interval <seconds>] [--limit N]");
|
|
160
|
+
console.error(" Poll a deployed program for new activity and upgrade-authority changes. Emits NDJSON.");
|
|
161
|
+
process.exit(2);
|
|
162
|
+
}
|
|
163
|
+
const { startChainWatch } = await import("./watchChain-F6INXAPA.js");
|
|
164
|
+
const rpcIdx = rest.indexOf("--rpc");
|
|
165
|
+
const rpcUrl = rpcIdx >= 0 ? rest[rpcIdx + 1] : void 0;
|
|
166
|
+
const intIdx = rest.indexOf("--interval");
|
|
167
|
+
const intervalMs = intIdx >= 0 ? parseInt(rest[intIdx + 1], 10) * 1e3 : void 0;
|
|
168
|
+
const limIdx = rest.indexOf("--limit");
|
|
169
|
+
const limit = limIdx >= 0 ? parseInt(rest[limIdx + 1], 10) : void 0;
|
|
170
|
+
const handle = startChainWatch(programId, { rpcUrl, intervalMs, limit });
|
|
171
|
+
process.on("SIGINT", () => {
|
|
172
|
+
handle.stop();
|
|
173
|
+
process.exit(0);
|
|
174
|
+
});
|
|
175
|
+
process.on("SIGTERM", () => {
|
|
176
|
+
handle.stop();
|
|
177
|
+
process.exit(0);
|
|
178
|
+
});
|
|
179
|
+
await new Promise(() => {
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (args[0] === "rico") {
|
|
183
|
+
await runRico(args.slice(1));
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}
|
|
186
|
+
if (args[0] === "firewall") {
|
|
187
|
+
await runFirewall(args.slice(1));
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
if (args[0] === "idl-rules") {
|
|
191
|
+
await runIdlRules(args.slice(1));
|
|
192
|
+
process.exit(0);
|
|
193
|
+
}
|
|
194
|
+
if (args[0] === "score") {
|
|
195
|
+
await runScore(args.slice(1));
|
|
196
|
+
process.exit(0);
|
|
197
|
+
}
|
|
198
|
+
if (args[0] === "pump-check") {
|
|
199
|
+
await runPumpCheck(args.slice(1));
|
|
200
|
+
process.exit(0);
|
|
201
|
+
}
|
|
202
|
+
if (args[0] === "batch") {
|
|
203
|
+
await runBatch(args.slice(1));
|
|
204
|
+
process.exit(0);
|
|
205
|
+
}
|
|
146
206
|
if (args[0] === "fix") {
|
|
147
207
|
await runFix(args.slice(1));
|
|
148
208
|
process.exit(0);
|
|
@@ -510,7 +570,7 @@ async function runDiff(argv) {
|
|
|
510
570
|
console.error(" e.g.: brainblast diff lodash@4.17.20 lodash@4.17.21");
|
|
511
571
|
process.exit(2);
|
|
512
572
|
}
|
|
513
|
-
const { diffVersions, renderDiffText, renderDiffMd, riskScore } = await import("./diff-KIR4PCBC.js");
|
|
573
|
+
const { diffVersions, renderDiffText, renderDiffMd: _renderDiffMd, riskScore } = await import("./diff-KIR4PCBC.js");
|
|
514
574
|
let result;
|
|
515
575
|
try {
|
|
516
576
|
result = await diffVersions(ecosystem, pkgName, fromVersion, toVersion);
|
|
@@ -538,3 +598,254 @@ Risk profile unchanged (${result.unchanged.length} advisory${result.unchanged.le
|
|
|
538
598
|
console.log("\nNo known advisories for either version.");
|
|
539
599
|
}
|
|
540
600
|
}
|
|
601
|
+
async function runRico(argv) {
|
|
602
|
+
const { analyzeToken, renderRicoText } = await import("./ricomaps-WTMWBBOY.js");
|
|
603
|
+
const { verifyTokenIdentity } = await import("./tokenRegistry-CYIUZHAZ.js");
|
|
604
|
+
const mint = argv.find((a) => !a.startsWith("--"));
|
|
605
|
+
if (!mint) {
|
|
606
|
+
console.error("usage: brainblast rico <mint> [--expect SYMBOL] [--api-key KEY] [--fail-on SCORE] [--offline] [--json]");
|
|
607
|
+
process.exit(2);
|
|
608
|
+
}
|
|
609
|
+
const expectIdx = argv.indexOf("--expect");
|
|
610
|
+
const expectSymbol = expectIdx >= 0 ? argv[expectIdx + 1] : void 0;
|
|
611
|
+
const apiKeyIdx = argv.indexOf("--api-key");
|
|
612
|
+
let apiKey = apiKeyIdx >= 0 ? argv[apiKeyIdx + 1] : void 0;
|
|
613
|
+
const failOnIdx = argv.indexOf("--fail-on");
|
|
614
|
+
const failOn = failOnIdx >= 0 ? parseInt(argv[failOnIdx + 1], 10) : 70;
|
|
615
|
+
const offline = argv.includes("--offline");
|
|
616
|
+
const jsonOut = argv.includes("--json");
|
|
617
|
+
let ricoResult = null;
|
|
618
|
+
if (!offline) {
|
|
619
|
+
ricoResult = await analyzeToken(mint, { apiKey });
|
|
620
|
+
if (!ricoResult.ok && ricoResult.kind === "auth") {
|
|
621
|
+
const readline = await import("readline");
|
|
622
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
623
|
+
const answer = await new Promise((resolve) => {
|
|
624
|
+
rl.question(
|
|
625
|
+
"\nRico Maps API key missing or invalid.\n [s] Skip quality scan\n [k] Enter API key\nChoice: ",
|
|
626
|
+
resolve
|
|
627
|
+
);
|
|
628
|
+
});
|
|
629
|
+
rl.close();
|
|
630
|
+
if (answer.trim().toLowerCase().startsWith("k")) {
|
|
631
|
+
const rl2 = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
632
|
+
apiKey = await new Promise((resolve) => {
|
|
633
|
+
rl2.question("API key: ", resolve);
|
|
634
|
+
});
|
|
635
|
+
rl2.close();
|
|
636
|
+
ricoResult = await analyzeToken(mint, { apiKey });
|
|
637
|
+
} else {
|
|
638
|
+
ricoResult = null;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
const claimedSymbol = ricoResult?.ok ? ricoResult.result.symbol : void 0;
|
|
643
|
+
const identity = await verifyTokenIdentity(mint, { expectSymbol, claimedSymbol, offline });
|
|
644
|
+
if (jsonOut) {
|
|
645
|
+
console.log(JSON.stringify({ identity, quality: ricoResult?.ok ? ricoResult.result : null }, null, 2));
|
|
646
|
+
} else {
|
|
647
|
+
const impTag = identity.impersonation ? " \u26A0 IMPERSONATION" : "";
|
|
648
|
+
const expectTag = identity.expectMismatch ? " \u26A0 EXPECT MISMATCH" : "";
|
|
649
|
+
console.log(`
|
|
650
|
+
Identity [${identity.status}]${impTag}${expectTag}`);
|
|
651
|
+
if (identity.symbol) console.log(` Symbol: ${identity.symbol}`);
|
|
652
|
+
if (identity.name) console.log(` Name: ${identity.name}`);
|
|
653
|
+
console.log(` Source: ${identity.source}`);
|
|
654
|
+
if (identity.impersonation && identity.canonicalMint) {
|
|
655
|
+
console.log(` Canonical ${identity.symbol} mint: ${identity.canonicalMint}`);
|
|
656
|
+
console.log(` This token: ${mint}`);
|
|
657
|
+
}
|
|
658
|
+
if (identity.detail) console.log(` Note: ${identity.detail}`);
|
|
659
|
+
if (ricoResult === null) {
|
|
660
|
+
console.log("\nQuality [skipped]");
|
|
661
|
+
} else if (!ricoResult.ok) {
|
|
662
|
+
console.log(`
|
|
663
|
+
Quality [error: ${ricoResult.kind}] ${ricoResult.error}`);
|
|
664
|
+
if (ricoResult.kind === "rate-limit" && ricoResult.retryAfterMs) {
|
|
665
|
+
console.log(` Retry after: ${Math.ceil(ricoResult.retryAfterMs / 1e3)}s`);
|
|
666
|
+
}
|
|
667
|
+
} else {
|
|
668
|
+
console.log(`
|
|
669
|
+
${renderRicoText(ricoResult.result)}`);
|
|
670
|
+
}
|
|
671
|
+
console.log("");
|
|
672
|
+
}
|
|
673
|
+
const highRisk = ricoResult?.ok && ricoResult.result.riskScore >= failOn;
|
|
674
|
+
if (identity.impersonation || identity.expectMismatch || highRisk) {
|
|
675
|
+
process.exit(1);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
async function runFirewall(argv) {
|
|
679
|
+
const { inspectTransaction, renderFirewallText } = await import("./firewall-HN5XJLGC.js");
|
|
680
|
+
const tx = argv.find((a) => !a.startsWith("--"));
|
|
681
|
+
if (!tx) {
|
|
682
|
+
console.error("usage: brainblast firewall <base64-tx> [--rpc URL] [--no-simulate] [--message-only] [--strict] [--json]");
|
|
683
|
+
console.error(" Inspect a serialized Solana transaction before an agent signs it.");
|
|
684
|
+
console.error(" Exit 1 on BLOCK verdict (or any WARN with --strict).");
|
|
685
|
+
process.exit(2);
|
|
686
|
+
}
|
|
687
|
+
const rpcIdx = argv.indexOf("--rpc");
|
|
688
|
+
const rpcUrl = rpcIdx >= 0 ? argv[rpcIdx + 1] : void 0;
|
|
689
|
+
const noSimulate = argv.includes("--no-simulate");
|
|
690
|
+
const messageOnly = argv.includes("--message-only");
|
|
691
|
+
const strict2 = argv.includes("--strict");
|
|
692
|
+
const jsonOut = argv.includes("--json");
|
|
693
|
+
let report2;
|
|
694
|
+
try {
|
|
695
|
+
report2 = await inspectTransaction(tx, { rpcUrl, simulate: !noSimulate, messageOnly });
|
|
696
|
+
} catch (e) {
|
|
697
|
+
console.error(`brainblast firewall: ${e?.message ?? String(e)}`);
|
|
698
|
+
process.exit(2);
|
|
699
|
+
}
|
|
700
|
+
if (jsonOut) {
|
|
701
|
+
console.log(JSON.stringify(report2, null, 2));
|
|
702
|
+
} else {
|
|
703
|
+
console.log(renderFirewallText(report2));
|
|
704
|
+
}
|
|
705
|
+
if (report2.verdict === "block" || strict2 && report2.verdict === "warn") {
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
async function runIdlRules(argv) {
|
|
710
|
+
const { readFileSync: readFileSync2, writeFileSync: writeFileSync3, mkdirSync: mkdirSync3 } = await import("fs");
|
|
711
|
+
const { join: join3 } = await import("path");
|
|
712
|
+
const { parseIdl, generateRulesFromIdl, renderRulesYaml } = await import("./idlRules-3KZML4NL.js");
|
|
713
|
+
const idlPath = argv.find((a) => !a.startsWith("--"));
|
|
714
|
+
if (!idlPath) {
|
|
715
|
+
console.error("usage: brainblast idl-rules <idl.json> [--out <dir>] [--json]");
|
|
716
|
+
console.error(" Generate brainblast rules from an Anchor IDL's account constraints.");
|
|
717
|
+
process.exit(2);
|
|
718
|
+
}
|
|
719
|
+
const outIdx = argv.indexOf("--out");
|
|
720
|
+
const outDir2 = outIdx >= 0 ? argv[outIdx + 1] : void 0;
|
|
721
|
+
const jsonOut = argv.includes("--json");
|
|
722
|
+
let idl;
|
|
723
|
+
try {
|
|
724
|
+
idl = parseIdl(JSON.parse(readFileSync2(idlPath, "utf8")));
|
|
725
|
+
} catch (e) {
|
|
726
|
+
console.error(`brainblast idl-rules: ${e?.message ?? String(e)}`);
|
|
727
|
+
process.exit(2);
|
|
728
|
+
}
|
|
729
|
+
const rules2 = generateRulesFromIdl(idl);
|
|
730
|
+
if (rules2.length === 0) {
|
|
731
|
+
console.error("brainblast idl-rules: IDL produced no rules (no instructions?)");
|
|
732
|
+
process.exit(1);
|
|
733
|
+
}
|
|
734
|
+
if (jsonOut) {
|
|
735
|
+
console.log(JSON.stringify(rules2, null, 2));
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
const yaml = renderRulesYaml(rules2);
|
|
739
|
+
if (outDir2) {
|
|
740
|
+
mkdirSync3(outDir2, { recursive: true });
|
|
741
|
+
const file = join3(outDir2, `${rules2[0].id}.yaml`);
|
|
742
|
+
writeFileSync3(file, yaml);
|
|
743
|
+
console.log(`Generated ${rules2.length} rule(s) \u2192 ${file}`);
|
|
744
|
+
console.log(` Run against your program: npx brainblast <program-dir> --packs <pack-with-this-rule>`);
|
|
745
|
+
} else {
|
|
746
|
+
console.log(yaml);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
async function runScore(argv) {
|
|
750
|
+
const { scoreProgram, renderScoreText, gradeAtLeast } = await import("./score-VLKER37D.js");
|
|
751
|
+
const { isValidSolanaAddress: isValidSolanaAddress2 } = await import("./trustGraph-4SSJOQKT.js");
|
|
752
|
+
const programId = argv.find((a) => !a.startsWith("--"));
|
|
753
|
+
if (!programId) {
|
|
754
|
+
console.error("usage: brainblast score <program-id> [--rpc URL] [--no-probe] [--min A|B|C|D|F] [--json]");
|
|
755
|
+
console.error(" Compute a 0-100 trust score + A-F grade for a deployed Solana program.");
|
|
756
|
+
process.exit(2);
|
|
757
|
+
}
|
|
758
|
+
if (!isValidSolanaAddress2(programId)) {
|
|
759
|
+
console.error(`brainblast score: not a valid Solana address: ${programId}`);
|
|
760
|
+
process.exit(2);
|
|
761
|
+
}
|
|
762
|
+
const rpcIdx = argv.indexOf("--rpc");
|
|
763
|
+
const rpcUrl = rpcIdx >= 0 ? argv[rpcIdx + 1] : void 0;
|
|
764
|
+
const noProbe = argv.includes("--no-probe");
|
|
765
|
+
const minIdx = argv.indexOf("--min");
|
|
766
|
+
const min = minIdx >= 0 ? argv[minIdx + 1] : void 0;
|
|
767
|
+
const jsonOut = argv.includes("--json");
|
|
768
|
+
let result;
|
|
769
|
+
try {
|
|
770
|
+
result = await scoreProgram(programId, { rpcUrl, probeRpc: !noProbe });
|
|
771
|
+
} catch (e) {
|
|
772
|
+
console.error(`brainblast score: ${e?.message ?? String(e)}`);
|
|
773
|
+
process.exit(1);
|
|
774
|
+
}
|
|
775
|
+
if (jsonOut) {
|
|
776
|
+
console.log(JSON.stringify(result, null, 2));
|
|
777
|
+
} else {
|
|
778
|
+
console.log(renderScoreText(result));
|
|
779
|
+
}
|
|
780
|
+
if (min && !gradeAtLeast(result.grade, min)) {
|
|
781
|
+
process.exit(1);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
async function runPumpCheck(argv) {
|
|
785
|
+
const { pumpPreflight, renderPreflightText } = await import("./pumpCheck-K2ESOBNU.js");
|
|
786
|
+
const mint = argv.find((a) => !a.startsWith("--"));
|
|
787
|
+
if (!mint) {
|
|
788
|
+
console.error("usage: brainblast pump-check <mint> [--rpc URL] [--api-key KEY] [--fail-on SCORE] [--offline] [--json]");
|
|
789
|
+
console.error(" Launch pre-flight: mint/freeze authority, identity, and Rico Maps forensics \u2192 GO/CAUTION/NO-GO.");
|
|
790
|
+
process.exit(2);
|
|
791
|
+
}
|
|
792
|
+
const rpcIdx = argv.indexOf("--rpc");
|
|
793
|
+
const rpcUrl = rpcIdx >= 0 ? argv[rpcIdx + 1] : void 0;
|
|
794
|
+
const keyIdx = argv.indexOf("--api-key");
|
|
795
|
+
const apiKey = keyIdx >= 0 ? argv[keyIdx + 1] : void 0;
|
|
796
|
+
const failIdx = argv.indexOf("--fail-on");
|
|
797
|
+
const failOnRisk = failIdx >= 0 ? parseInt(argv[failIdx + 1], 10) : void 0;
|
|
798
|
+
const offline = argv.includes("--offline");
|
|
799
|
+
const jsonOut = argv.includes("--json");
|
|
800
|
+
let report2;
|
|
801
|
+
try {
|
|
802
|
+
report2 = await pumpPreflight(mint, { rpcUrl, apiKey, failOnRisk, offline });
|
|
803
|
+
} catch (e) {
|
|
804
|
+
console.error(`brainblast pump-check: ${e?.message ?? String(e)}`);
|
|
805
|
+
process.exit(2);
|
|
806
|
+
}
|
|
807
|
+
if (jsonOut) {
|
|
808
|
+
console.log(JSON.stringify(report2, null, 2));
|
|
809
|
+
} else {
|
|
810
|
+
console.log(renderPreflightText(report2));
|
|
811
|
+
}
|
|
812
|
+
if (report2.verdict === "NO-GO") process.exit(1);
|
|
813
|
+
}
|
|
814
|
+
async function runBatch(argv) {
|
|
815
|
+
const { readFileSync: readFileSync2 } = await import("fs");
|
|
816
|
+
const { batchScan, parseMintList, renderBatchText } = await import("./batchScan-JR2G5JCF.js");
|
|
817
|
+
const file = argv.find((a) => !a.startsWith("--"));
|
|
818
|
+
if (!file) {
|
|
819
|
+
console.error("usage: brainblast batch <file> [--concurrency N] [--api-key KEY] [--fail-on SCORE] [--offline] [--json]");
|
|
820
|
+
console.error(" Risk-rank a list of contract addresses (newline-separated or JSON array).");
|
|
821
|
+
process.exit(2);
|
|
822
|
+
}
|
|
823
|
+
let mints;
|
|
824
|
+
try {
|
|
825
|
+
mints = parseMintList(readFileSync2(file, "utf8"));
|
|
826
|
+
} catch (e) {
|
|
827
|
+
console.error(`brainblast batch: ${e?.message ?? String(e)}`);
|
|
828
|
+
process.exit(2);
|
|
829
|
+
}
|
|
830
|
+
if (mints.length === 0) {
|
|
831
|
+
console.error("brainblast batch: no addresses found in file");
|
|
832
|
+
process.exit(2);
|
|
833
|
+
}
|
|
834
|
+
const concIdx = argv.indexOf("--concurrency");
|
|
835
|
+
const concurrency = concIdx >= 0 ? parseInt(argv[concIdx + 1], 10) : void 0;
|
|
836
|
+
const keyIdx = argv.indexOf("--api-key");
|
|
837
|
+
const apiKey = keyIdx >= 0 ? argv[keyIdx + 1] : void 0;
|
|
838
|
+
const failIdx = argv.indexOf("--fail-on");
|
|
839
|
+
const failOnRisk = failIdx >= 0 ? parseInt(argv[failIdx + 1], 10) : void 0;
|
|
840
|
+
const offline = argv.includes("--offline");
|
|
841
|
+
const jsonOut = argv.includes("--json");
|
|
842
|
+
const result = await batchScan(mints, { concurrency, apiKey, failOnRisk, offline });
|
|
843
|
+
if (jsonOut) {
|
|
844
|
+
console.log(JSON.stringify(result, null, 2));
|
|
845
|
+
} else {
|
|
846
|
+
console.log(renderBatchText(result));
|
|
847
|
+
}
|
|
848
|
+
if (result.summary.impersonators > 0 || result.summary.highRisk > 0) {
|
|
849
|
+
process.exit(1);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KNOWN_PROGRAMS,
|
|
3
|
+
analyzeInstructions,
|
|
4
|
+
decodeTransaction,
|
|
5
|
+
inspectTransaction,
|
|
6
|
+
parseCpiPrograms,
|
|
7
|
+
renderFirewallText
|
|
8
|
+
} from "./chunk-HL7NVANZ.js";
|
|
9
|
+
import "./chunk-VG5FMOLW.js";
|
|
10
|
+
import "./chunk-3RG5ZIWI.js";
|
|
11
|
+
export {
|
|
12
|
+
KNOWN_PROGRAMS,
|
|
13
|
+
analyzeInstructions,
|
|
14
|
+
decodeTransaction,
|
|
15
|
+
inspectTransaction,
|
|
16
|
+
parseCpiPrograms,
|
|
17
|
+
renderFirewallText
|
|
18
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildConstraintParams,
|
|
3
|
+
generateRulesFromIdl,
|
|
4
|
+
idlProgramName,
|
|
5
|
+
parseIdl,
|
|
6
|
+
renderRulesYaml,
|
|
7
|
+
toSnakeCase
|
|
8
|
+
} from "./chunk-O5Z4ZJHC.js";
|
|
9
|
+
import "./chunk-3RG5ZIWI.js";
|
|
10
|
+
export {
|
|
11
|
+
buildConstraintParams,
|
|
12
|
+
generateRulesFromIdl,
|
|
13
|
+
idlProgramName,
|
|
14
|
+
parseIdl,
|
|
15
|
+
renderRulesYaml,
|
|
16
|
+
toSnakeCase
|
|
17
|
+
};
|