sol2uml 2.5.3 → 2.5.5

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 CHANGED
@@ -55,7 +55,8 @@ Options:
55
55
  -f, --outputFormat <value> output file format. (choices: "svg", "png", "dot", "all", default: "svg")
56
56
  -o, --outputFileName <value> output file name
57
57
  -i, --ignoreFilesOrFolders <filesOrFolders> comma separated list of files or folders to ignore
58
- -n, --network <network> Ethereum network (choices: "mainnet", "goerli", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis", default: "mainnet", env: ETH_NETWORK)
58
+ -n, --network <network> Ethereum network (choices: "mainnet", "goerli", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam",
59
+ "optimism", "gnosis", "celo", default: "mainnet", env: ETH_NETWORK)
59
60
  -k, --apiKey <key> Blockchain explorer API key. eg Etherscan, Arbiscan, Optimism, BscScan, CronoScan, FTMScan, PolygonScan or SnowTrace API key (env: SCAN_API_KEY)
60
61
  -bc, --backColor <color> Canvas background color. "none" will use a transparent canvas. (default: "white")
61
62
  -sc, --shapeColor <color> Basic drawing color for graphics, not text (default: "black")
@@ -192,6 +193,8 @@ Arguments:
192
193
 
193
194
  Options:
194
195
  -l, --lineBuffer <value> Minimum number of lines before and after changes (default: "4")
196
+ --aFile <value> Contract A source code filename without the .sol extension. (default: compares all source files)
197
+ --bFile <value> Contract B source code filename without the .sol extension. (default: aFile if specified)
195
198
  -s, --saveFiles Save the flattened contract code to the filesystem. The file names will be the contract address with a .sol extension. (default: false)
196
199
  -h, --help display help for command
197
200
  ```
@@ -329,6 +332,25 @@ To access your local changes on your machine globally.
329
332
 
330
333
  `npm link`
331
334
 
335
+ # Publish
336
+
337
+ Commands to publish a new package version.
338
+
339
+ ```bash
340
+ npm run prettier
341
+ npm run clean
342
+ npm run package-lock
343
+ npm run build
344
+ npm run permit
345
+ # make tx2uml globally available for local testing
346
+ npm link
347
+ # check all the files are included in the npm package
348
+ npm pack --dry-run
349
+ npm publish
350
+ ```
351
+
352
+ Then create a new release on GitHub https://github.com/naddison36/sol2uml/releases
353
+
332
354
  # About
333
355
 
334
356
  This is a rewrite of the Richard Ramos's [solidity-diagram-gen](https://github.com/richard-ramos/solidity-diagram-gen) tool which no longer works as it uses [solidity-parser](https://www.npmjs.com/package/solidity-parser/v/0.4.0) which cannot handle newer Solidity syntax like `constructor`.
@@ -102,7 +102,7 @@ function convertAST2UmlClasses(node, relativePath, remappings, filesystem = fals
102
102
  })
103
103
  : [],
104
104
  };
105
- debug(`Added filesystem import ${newImport.absolutePath} with class names ${newImport.classNames}`);
105
+ debug(`Added filesystem import ${newImport.absolutePath} with class names ${newImport.classNames.map((i) => i.className)}`);
106
106
  imports.push(newImport);
107
107
  }
108
108
  catch (err) {
@@ -87,7 +87,7 @@ function loadWeightedDirectedGraph(umlClasses) {
87
87
  continue;
88
88
  }
89
89
  const isTarget = umlClasses.find((u) => u.id === targetUmlClass.id);
90
- debug(`isTarget ${isTarget} Adding edge from ${sourceUmlClass.name} with id ${sourceUmlClass.id} to ${targetUmlClass.name} with id ${targetUmlClass.id} and type ${targetUmlClass.stereotype}`);
90
+ debug(`isTarget ${!!isTarget}: Adding edge from ${sourceUmlClass.name} with id ${sourceUmlClass.id} to ${targetUmlClass.name} with id ${targetUmlClass.id} and type ${targetUmlClass.stereotype}`);
91
91
  weightedDirectedGraph.addEdge(new js_graph_algorithms_1.Edge(sourceUmlClass.id, targetUmlClass.id, 1));
92
92
  }
93
93
  }
@@ -4,7 +4,7 @@ export interface Remapping {
4
4
  from: RegExp;
5
5
  to: string;
6
6
  }
7
- export declare const networks: readonly ["mainnet", "goerli", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis"];
7
+ export declare const networks: readonly ["mainnet", "goerli", "sepolia", "polygon", "arbitrum", "avalanche", "bsc", "crono", "fantom", "moonbeam", "optimism", "gnosis", "celo"];
8
8
  export type Network = (typeof networks)[number];
9
9
  export declare class EtherscanParser {
10
10
  protected apikey: string;
@@ -26,7 +26,7 @@ export declare class EtherscanParser {
26
26
  * @param contractAddress Ethereum contract address with a 0x prefix
27
27
  * @return Promise string of Solidity code
28
28
  */
29
- getSolidityCode(contractAddress: string): Promise<{
29
+ getSolidityCode(contractAddress: string, filename?: string): Promise<{
30
30
  solidityCode: string;
31
31
  contractName: string;
32
32
  }>;
@@ -39,8 +39,9 @@ export declare class EtherscanParser {
39
39
  /**
40
40
  * Calls Etherscan to get the verified source code for the specified contract address
41
41
  * @param contractAddress Ethereum contract address with a 0x prefix
42
+ * @oaram filename optional, case-sensitive name of the source file without the .sol
42
43
  */
43
- getSourceCode(contractAddress: string): Promise<{
44
+ getSourceCode(contractAddress: string, filename?: string): Promise<{
44
45
  files: readonly {
45
46
  code: string;
46
47
  filename: string;
@@ -9,6 +9,7 @@ const parser_1 = require("@solidity-parser/parser");
9
9
  const converterAST2Classes_1 = require("./converterAST2Classes");
10
10
  const filterClasses_1 = require("./filterClasses");
11
11
  const regEx_1 = require("./utils/regEx");
12
+ const path_1 = __importDefault(require("path"));
12
13
  require('axios-debug-log');
13
14
  const debug = require('debug')('sol2uml');
14
15
  exports.networks = [
@@ -24,6 +25,7 @@ exports.networks = [
24
25
  'moonbeam',
25
26
  'optimism',
26
27
  'gnosis',
28
+ 'celo',
27
29
  ];
28
30
  class EtherscanParser {
29
31
  constructor(apikey = 'ZAD4UI2RCXCQTP38EXS3UY2MPHFU5H9KB1', network = 'mainnet') {
@@ -71,6 +73,10 @@ class EtherscanParser {
71
73
  this.url = 'https://api.gnosisscan.io/api';
72
74
  this.apikey = '2RWGXIWK538EJ8XSP9DE2JUINSCG7UCSJB';
73
75
  }
76
+ else if (network === 'celo') {
77
+ this.url = 'https://api.celoscan.io/api';
78
+ this.apikey = 'JBV78T5KP15W7WKKKD6KC4J8RX2F4PK8AF';
79
+ }
74
80
  else {
75
81
  this.url = `https://api-${network}.etherscan.io/api`;
76
82
  }
@@ -100,8 +106,8 @@ class EtherscanParser {
100
106
  * @param contractAddress Ethereum contract address with a 0x prefix
101
107
  * @return Promise string of Solidity code
102
108
  */
103
- async getSolidityCode(contractAddress) {
104
- const { files, contractName, compilerVersion, remappings } = await this.getSourceCode(contractAddress);
109
+ async getSolidityCode(contractAddress, filename) {
110
+ const { files, contractName, compilerVersion, remappings } = await this.getSourceCode(contractAddress, filename);
105
111
  // Parse the UmlClasses from the Solidity code in each file
106
112
  let umlClasses = [];
107
113
  for (const file of files) {
@@ -137,7 +143,7 @@ class EtherscanParser {
137
143
  // match whitespace before import
138
144
  // and characters after import up to ;
139
145
  // replace all in file and match across multiple lines
140
- const removedImports = removedPragmaSolidity.replace(/(\s)(import.*;)/gm, '$1/* $2 */');
146
+ const removedImports = removedPragmaSolidity.replace(/^\s*?(import.*?;)/gms, '/* $1 */');
141
147
  // Rename SPDX-License-Identifier to SPDX--License-Identifier so the merged file will compile
142
148
  const removedSPDX = removedImports.replace(/SPDX-/, 'SPDX--');
143
149
  solidityCode += removedSPDX;
@@ -164,8 +170,9 @@ class EtherscanParser {
164
170
  /**
165
171
  * Calls Etherscan to get the verified source code for the specified contract address
166
172
  * @param contractAddress Ethereum contract address with a 0x prefix
173
+ * @oaram filename optional, case-sensitive name of the source file without the .sol
167
174
  */
168
- async getSourceCode(contractAddress) {
175
+ async getSourceCode(contractAddress, filename) {
169
176
  const description = `get verified source code for address ${contractAddress} from Etherscan API.`;
170
177
  try {
171
178
  debug(`About to get Solidity source code for ${contractAddress} from ${this.url}`);
@@ -226,8 +233,16 @@ class EtherscanParser {
226
233
  filename: contractAddress,
227
234
  };
228
235
  });
236
+ let files = results.flat(1);
237
+ const filenameWithExt = filename + '.sol';
238
+ if (filename) {
239
+ files = files.filter((r) => path_1.default.parse(r.filename).base == filenameWithExt);
240
+ if (!files?.length) {
241
+ throw new Error(`Failed to find source file "${filename}" for contract ${contractAddress}`);
242
+ }
243
+ }
229
244
  return {
230
- files: results.flat(1),
245
+ files,
231
246
  contractName: response.data.result[0].ContractName,
232
247
  compilerVersion: response.data.result[0].CompilerVersion,
233
248
  remappings,
package/lib/sol2uml.js CHANGED
@@ -225,6 +225,8 @@ The line numbers are from contract B. There are no line numbers for the red sect
225
225
  .argument('<addressA>', 'Contract address in hexadecimal format with a 0x prefix of the first contract.')
226
226
  .argument('<addressB>', 'Contract address in hexadecimal format with a 0x prefix of the second contract.')
227
227
  .addOption(new commander_1.Option('-l, --lineBuffer <value>', 'Minimum number of lines before and after changes').default('4'))
228
+ .addOption(new commander_1.Option('-af --aFile <value>', 'Contract A source code filename without the .sol extension. (default: compares all source files)'))
229
+ .addOption(new commander_1.Option('-bf --bFile <value>', 'Contract B source code filename without the .sol extension. (default: aFile if specified)'))
228
230
  .option('-s, --saveFiles', 'Save the flattened contract code to the filesystem. The file names will be the contract address with a .sol extension.', false)
229
231
  .action(async (addressA, addressB, options, command) => {
230
232
  try {
@@ -239,8 +241,8 @@ The line numbers are from contract B. There are no line numbers for the red sect
239
241
  throw Error(`Invalid line buffer "${options.lineBuffer}". Must be a number`);
240
242
  const etherscanParser = new parserEtherscan_1.EtherscanParser(combinedOptions.apiKey, combinedOptions.network);
241
243
  // Get verified Solidity code from Etherscan and flatten
242
- const { solidityCode: codeA, contractName: contractNameA } = await etherscanParser.getSolidityCode(addressA);
243
- const { solidityCode: codeB, contractName: contractNameB } = await etherscanParser.getSolidityCode(addressB);
244
+ const { solidityCode: codeA, contractName: contractNameA } = await etherscanParser.getSolidityCode(addressA, combinedOptions.aFile);
245
+ const { solidityCode: codeB, contractName: contractNameB } = await etherscanParser.getSolidityCode(addressB, combinedOptions.bFile || combinedOptions.aFile);
244
246
  console.log(`Difference between`);
245
247
  console.log(`A. ${addressA} ${contractNameA} on ${combinedOptions.network}`);
246
248
  console.log(`B. ${addressB} ${contractNameB} on ${combinedOptions.network}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sol2uml",
3
- "version": "2.5.3",
3
+ "version": "2.5.5",
4
4
  "description": "Solidity contract visualisation tool.",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -36,7 +36,7 @@
36
36
  "klaw": "^4.1.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@openzeppelin/contracts": "4.8.0",
39
+ "@openzeppelin/contracts": "^4.8.2",
40
40
  "@types/diff-match-patch": "^1.0.32",
41
41
  "@types/jest": "^29.4.0",
42
42
  "@types/klaw": "^3.0.3",