brainblast 0.5.1 → 0.5.2

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.
@@ -1042,10 +1042,48 @@ JWKS must come from Privy's published JWKS endpoint for your app.`
1042
1042
  };
1043
1043
  };
1044
1044
 
1045
+ // src/fixers/literalMultiplierWrongConstant.ts
1046
+ import { SyntaxKind as SyntaxKind11 } from "ts-morph";
1047
+ function callName6(call) {
1048
+ const exp = call.getExpression();
1049
+ if (exp.getKind() === SyntaxKind11.Identifier) return exp.getText();
1050
+ if (exp.getKind() === SyntaxKind11.PropertyAccessExpression) {
1051
+ return exp.asKind(SyntaxKind11.PropertyAccessExpression).getName();
1052
+ }
1053
+ return "";
1054
+ }
1055
+ function findIdentifier(node, name) {
1056
+ if (node.getKind() === SyntaxKind11.Identifier && node.getText() === name) return node;
1057
+ return node.getDescendantsOfKind(SyntaxKind11.Identifier).find((id) => id.getText() === name);
1058
+ }
1059
+ var fixLiteralMultiplierWrongConstant = (c, p, outcome) => {
1060
+ if (outcome.result !== "fail") return void 0;
1061
+ const calls = c.fn.getDescendantsOfKind(SyntaxKind11.CallExpression).filter((call) => callName6(call) === p.call);
1062
+ if (calls.length === 0) return void 0;
1063
+ const arg = calls[0].getArguments()[p.argIndex];
1064
+ if (!arg) return void 0;
1065
+ const forbidden = Array.isArray(p.forbiddenIdentifiers) ? p.forbiddenIdentifiers : [];
1066
+ const forbiddenNode = forbidden.map((name) => findIdentifier(arg, name)).find((n) => n);
1067
+ if (!forbiddenNode) return void 0;
1068
+ const expected = Array.isArray(p.expectedIdentifiers) ? p.expectedIdentifiers : [];
1069
+ const expectedName = expected.find((name) => c.params.includes(name));
1070
+ if (!expectedName) {
1071
+ return {
1072
+ summary: `Scale by the mint's decimals instead of ${forbiddenNode.getText()}`,
1073
+ suggestion: `'${forbiddenNode.getText()}' is the native-SOL lamports constant (1e9), not the mint's decimals. Add a 'decimals: number' parameter to this function (threaded from the mint's configuration) and scale the amount with '10 ** decimals' instead of '${forbiddenNode.getText()}'.`
1074
+ };
1075
+ }
1076
+ return {
1077
+ summary: `Scale by 10 ** ${expectedName} instead of ${forbiddenNode.getText()}`,
1078
+ diff: buildDiff(forbiddenNode, `10 ** ${expectedName}`)
1079
+ };
1080
+ };
1081
+
1045
1082
  // src/fixers/index.ts
1046
1083
  var registry2 = {
1047
1084
  "positional-arg-identity": fixPositionalArgIdentity,
1048
- "required-call-with-options": fixRequiredCallWithOptions
1085
+ "required-call-with-options": fixRequiredCallWithOptions,
1086
+ "literal-multiplier-wrong-constant": fixLiteralMultiplierWrongConstant
1049
1087
  };
1050
1088
  function runFixer(kind, c, params, outcome) {
1051
1089
  if (outcome.result !== "fail") return void 0;
@@ -1995,7 +2033,7 @@ function renderTrustGraphMd(g) {
1995
2033
  }
1996
2034
 
1997
2035
  // src/costAnalysis.ts
1998
- import { Project as Project2, SyntaxKind as SyntaxKind11 } from "ts-morph";
2036
+ import { Project as Project2, SyntaxKind as SyntaxKind12 } from "ts-morph";
1999
2037
  var LAMPORTS_PER_BYTE_YEAR = 3480;
2000
2038
  var EXEMPTION_THRESHOLD = 2;
2001
2039
  var OVERHEAD_BYTES = 128;
@@ -2076,11 +2114,11 @@ var KNOWN_FLOWS = [
2076
2114
  }
2077
2115
  ];
2078
2116
  var LOOP_NODE_KINDS = /* @__PURE__ */ new Set([
2079
- SyntaxKind11.ForStatement,
2080
- SyntaxKind11.ForOfStatement,
2081
- SyntaxKind11.ForInStatement,
2082
- SyntaxKind11.WhileStatement,
2083
- SyntaxKind11.DoStatement
2117
+ SyntaxKind12.ForStatement,
2118
+ SyntaxKind12.ForOfStatement,
2119
+ SyntaxKind12.ForInStatement,
2120
+ SyntaxKind12.WhileStatement,
2121
+ SyntaxKind12.DoStatement
2084
2122
  ]);
2085
2123
  var ARRAY_METHOD_LOOPS = /* @__PURE__ */ new Set(["map", "forEach", "flatMap", "reduce", "filter"]);
2086
2124
  function isInsideLoop(node) {
@@ -2088,12 +2126,12 @@ function isInsideLoop(node) {
2088
2126
  while (cur) {
2089
2127
  const k = cur.getKind?.();
2090
2128
  if (k !== void 0 && LOOP_NODE_KINDS.has(k)) {
2091
- return { scalable: true, note: `call is inside a ${SyntaxKind11[k]} \u2014 cost scales with loop iterations` };
2129
+ return { scalable: true, note: `call is inside a ${SyntaxKind12[k]} \u2014 cost scales with loop iterations` };
2092
2130
  }
2093
- if (k === SyntaxKind11.CallExpression) {
2131
+ if (k === SyntaxKind12.CallExpression) {
2094
2132
  const expr = cur.getExpression?.();
2095
- if (expr?.getKind?.() === SyntaxKind11.PropertyAccessExpression) {
2096
- const name = expr.asKind?.(SyntaxKind11.PropertyAccessExpression)?.getName?.();
2133
+ if (expr?.getKind?.() === SyntaxKind12.PropertyAccessExpression) {
2134
+ const name = expr.asKind?.(SyntaxKind12.PropertyAccessExpression)?.getName?.();
2097
2135
  if (name && ARRAY_METHOD_LOOPS.has(name)) {
2098
2136
  return { scalable: true, note: `call is inside .${name}() \u2014 cost scales with array length` };
2099
2137
  }
@@ -2107,7 +2145,7 @@ function detectPriorityFee(targetDir) {
2107
2145
  const project = new Project2({ skipAddingFilesFromTsConfig: true });
2108
2146
  for (const file of walk(targetDir)) {
2109
2147
  const sf = project.addSourceFileAtPath(file);
2110
- const calls = sf.getDescendantsOfKind(SyntaxKind11.CallExpression);
2148
+ const calls = sf.getDescendantsOfKind(SyntaxKind12.CallExpression);
2111
2149
  for (const ce of calls) {
2112
2150
  const expr = ce.getExpression();
2113
2151
  const text = expr.getText();
@@ -2135,22 +2173,22 @@ function detectAccountFlows(targetDir) {
2135
2173
  const importedModules = new Set(
2136
2174
  sf.getImportDeclarations().map((d) => d.getModuleSpecifierValue())
2137
2175
  );
2138
- for (const ce of sf.getDescendantsOfKind(SyntaxKind11.CallExpression)) {
2176
+ for (const ce of sf.getDescendantsOfKind(SyntaxKind12.CallExpression)) {
2139
2177
  const expr = ce.getExpression();
2140
- let callName6 = null;
2141
- if (expr.getKind() === SyntaxKind11.Identifier) {
2142
- callName6 = expr.getText();
2143
- } else if (expr.getKind() === SyntaxKind11.PropertyAccessExpression) {
2144
- callName6 = expr.asKind(SyntaxKind11.PropertyAccessExpression).getName();
2178
+ let callName7 = null;
2179
+ if (expr.getKind() === SyntaxKind12.Identifier) {
2180
+ callName7 = expr.getText();
2181
+ } else if (expr.getKind() === SyntaxKind12.PropertyAccessExpression) {
2182
+ callName7 = expr.asKind(SyntaxKind12.PropertyAccessExpression).getName();
2145
2183
  }
2146
- if (!callName6) continue;
2147
- const known = callIndex.get(callName6);
2184
+ if (!callName7) continue;
2185
+ const known = callIndex.get(callName7);
2148
2186
  if (!known) continue;
2149
2187
  if (!importedModules.has(known.module)) continue;
2150
2188
  const lamports = rentExemptMinimum(known.dataLen);
2151
2189
  const { scalable, note } = isInsideLoop(ce);
2152
2190
  flows.push({
2153
- call: callName6,
2191
+ call: callName7,
2154
2192
  module: known.module,
2155
2193
  accountType: known.accountType,
2156
2194
  file,
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  submitTelemetry,
21
21
  telemetryFilePath,
22
22
  validatePack
23
- } from "./chunk-LOPYKIXE.js";
23
+ } from "./chunk-EYFKA33G.js";
24
24
 
25
25
  // src/cli.ts
26
26
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ import {
50
50
  testKinds,
51
51
  validatePack,
52
52
  validatePackManifest
53
- } from "./chunk-LOPYKIXE.js";
53
+ } from "./chunk-EYFKA33G.js";
54
54
 
55
55
  // src/generate.ts
56
56
  import { writeFileSync, mkdirSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainblast",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "type": "module",
5
5
  "description": "Deterministic auditor for catastrophic AI-integration bugs: scan a repo, find the silent money/auth traps, and generate the behavioral test that proves they're fixed.",
6
6
  "keywords": [