aboutsummaryrefslogtreecommitdiffstats
path: root/packages/sol-compiler/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'packages/sol-compiler/src/utils')
-rw-r--r--packages/sol-compiler/src/utils/compiler.ts107
-rw-r--r--packages/sol-compiler/src/utils/constants.ts5
-rw-r--r--packages/sol-compiler/src/utils/encoder.ts18
-rw-r--r--packages/sol-compiler/src/utils/fs_wrapper.ts12
-rw-r--r--packages/sol-compiler/src/utils/types.ts79
-rw-r--r--packages/sol-compiler/src/utils/utils.ts6
6 files changed, 227 insertions, 0 deletions
diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts
new file mode 100644
index 000000000..c571b2581
--- /dev/null
+++ b/packages/sol-compiler/src/utils/compiler.ts
@@ -0,0 +1,107 @@
+import { ContractSource, ContractSources } from '@0xproject/sol-resolver';
+import { logUtils } from '@0xproject/utils';
+import * as _ from 'lodash';
+import * as path from 'path';
+import * as solc from 'solc';
+
+import { constants } from './constants';
+import { fsWrapper } from './fs_wrapper';
+import { ContractArtifact } from './types';
+
+/**
+ * Gets contract data on network or returns if an artifact does not exist.
+ * @param artifactsDir Path to the artifacts directory.
+ * @param contractName Name of contract.
+ * @return Contract data on network or undefined.
+ */
+export async function getContractArtifactIfExistsAsync(
+ artifactsDir: string,
+ contractName: string,
+): Promise<ContractArtifact | void> {
+ let contractArtifact;
+ const currentArtifactPath = `${artifactsDir}/${contractName}.json`;
+ try {
+ const opts = {
+ encoding: 'utf8',
+ };
+ const contractArtifactString = await fsWrapper.readFileAsync(currentArtifactPath, opts);
+ contractArtifact = JSON.parse(contractArtifactString);
+ return contractArtifact;
+ } catch (err) {
+ logUtils.log(`Artifact for ${contractName} does not exist`);
+ return undefined;
+ }
+}
+
+/**
+ * Creates a directory if it does not already exist.
+ * @param artifactsDir Path to the directory.
+ */
+export async function createDirIfDoesNotExistAsync(dirPath: string): Promise<void> {
+ if (!fsWrapper.doesPathExistSync(dirPath)) {
+ logUtils.log(`Creating directory at ${dirPath}...`);
+ await fsWrapper.mkdirAsync(dirPath);
+ }
+}
+
+/**
+ * Searches Solidity source code for compiler version range.
+ * @param source Source code of contract.
+ * @return Solc compiler version range.
+ */
+export function parseSolidityVersionRange(source: string): string {
+ const SOLIDITY_VERSION_RANGE_REGEX = /pragma\s+solidity\s+(.*);/;
+ const solcVersionRangeMatch = source.match(SOLIDITY_VERSION_RANGE_REGEX);
+ if (_.isNull(solcVersionRangeMatch)) {
+ throw new Error('Could not find Solidity version range in source');
+ }
+ const solcVersionRange = solcVersionRangeMatch[1];
+ return solcVersionRange;
+}
+
+/**
+ * Normalizes the path found in the error message.
+ * Example: converts 'base/Token.sol:6:46: Warning: Unused local variable'
+ * to 'Token.sol:6:46: Warning: Unused local variable'
+ * This is used to prevent logging the same error multiple times.
+ * @param errMsg An error message from the compiled output.
+ * @return The error message with directories truncated from the contract path.
+ */
+export function getNormalizedErrMsg(errMsg: string): string {
+ const SOLIDITY_FILE_EXTENSION_REGEX = /(.*\.sol)/;
+ const errPathMatch = errMsg.match(SOLIDITY_FILE_EXTENSION_REGEX);
+ if (_.isNull(errPathMatch)) {
+ throw new Error('Could not find a path in error message');
+ }
+ const errPath = errPathMatch[0];
+ const baseContract = path.basename(errPath);
+ const normalizedErrMsg = errMsg.replace(errPath, baseContract);
+ return normalizedErrMsg;
+}
+
+/**
+ * Parses the contract source code and extracts the dendencies
+ * @param source Contract source code
+ * @return List of dependendencies
+ */
+export function parseDependencies(contractSource: ContractSource): string[] {
+ // TODO: Use a proper parser
+ const source = contractSource.source;
+ const IMPORT_REGEX = /(import\s)/;
+ const DEPENDENCY_PATH_REGEX = /"([^"]+)"/; // Source: https://github.com/BlockChainCompany/soljitsu/blob/master/lib/shared.js
+ const dependencies: string[] = [];
+ const lines = source.split('\n');
+ _.forEach(lines, line => {
+ if (!_.isNull(line.match(IMPORT_REGEX))) {
+ const dependencyMatch = line.match(DEPENDENCY_PATH_REGEX);
+ if (!_.isNull(dependencyMatch)) {
+ let dependencyPath = dependencyMatch[1];
+ if (dependencyPath.startsWith('.')) {
+ dependencyPath = path.join(path.dirname(contractSource.path), dependencyPath);
+ }
+ dependencies.push(dependencyPath);
+ }
+ }
+ });
+ return dependencies;
+}
diff --git a/packages/sol-compiler/src/utils/constants.ts b/packages/sol-compiler/src/utils/constants.ts
new file mode 100644
index 000000000..df2ddb3b2
--- /dev/null
+++ b/packages/sol-compiler/src/utils/constants.ts
@@ -0,0 +1,5 @@
+export const constants = {
+ SOLIDITY_FILE_EXTENSION: '.sol',
+ BASE_COMPILER_URL: 'https://ethereum.github.io/solc-bin/bin/',
+ LATEST_ARTIFACT_VERSION: '2.0.0',
+};
diff --git a/packages/sol-compiler/src/utils/encoder.ts b/packages/sol-compiler/src/utils/encoder.ts
new file mode 100644
index 000000000..806efbbca
--- /dev/null
+++ b/packages/sol-compiler/src/utils/encoder.ts
@@ -0,0 +1,18 @@
+import { AbiDefinition, AbiType, ContractAbi, DataItem } from '@0xproject/types';
+import * as _ from 'lodash';
+import * as web3Abi from 'web3-eth-abi';
+
+export const encoder = {
+ encodeConstructorArgsFromAbi(args: any[], abi: ContractAbi): string {
+ const constructorTypes: string[] = [];
+ _.each(abi, (element: AbiDefinition) => {
+ if (element.type === AbiType.Constructor) {
+ _.each(element.inputs, (input: DataItem) => {
+ constructorTypes.push(input.type);
+ });
+ }
+ });
+ const encodedParameters = web3Abi.encodeParameters(constructorTypes, args);
+ return encodedParameters;
+ },
+};
diff --git a/packages/sol-compiler/src/utils/fs_wrapper.ts b/packages/sol-compiler/src/utils/fs_wrapper.ts
new file mode 100644
index 000000000..e02c83f27
--- /dev/null
+++ b/packages/sol-compiler/src/utils/fs_wrapper.ts
@@ -0,0 +1,12 @@
+import { promisify } from '@0xproject/utils';
+import * as fs from 'fs';
+
+export const fsWrapper = {
+ readdirAsync: promisify<string[]>(fs.readdir),
+ readFileAsync: promisify<string>(fs.readFile),
+ writeFileAsync: promisify<undefined>(fs.writeFile),
+ mkdirAsync: promisify<undefined>(fs.mkdir),
+ doesPathExistSync: fs.existsSync,
+ rmdirSync: fs.rmdirSync,
+ removeFileAsync: promisify<undefined>(fs.unlink),
+};
diff --git a/packages/sol-compiler/src/utils/types.ts b/packages/sol-compiler/src/utils/types.ts
new file mode 100644
index 000000000..b12a11b79
--- /dev/null
+++ b/packages/sol-compiler/src/utils/types.ts
@@ -0,0 +1,79 @@
+import { ContractAbi, Provider, TxData } from '@0xproject/types';
+import * as solc from 'solc';
+import * as Web3 from 'web3';
+import * as yargs from 'yargs';
+
+export enum AbiType {
+ Function = 'function',
+ Constructor = 'constructor',
+ Event = 'event',
+ Fallback = 'fallback',
+}
+
+export interface ContractArtifact extends ContractVersionData {
+ schemaVersion: string;
+ contractName: string;
+ networks: ContractNetworks;
+}
+
+export interface ContractVersionData {
+ compiler: {
+ name: 'solc';
+ version: string;
+ settings: solc.CompilerSettings;
+ };
+ sources: {
+ [sourceName: string]: {
+ id: number;
+ };
+ };
+ sourceCodes: {
+ [sourceName: string]: string;
+ };
+ sourceTreeHashHex: string;
+ compilerOutput: solc.StandardContractOutput;
+}
+
+export interface ContractNetworks {
+ [networkId: number]: ContractNetworkData;
+}
+
+export interface ContractNetworkData {
+ address: string;
+ links: {
+ [linkName: string]: string;
+ };
+ constructorArgs: string;
+}
+
+export interface SolcErrors {
+ [key: string]: boolean;
+}
+
+export interface CompilerOptions {
+ contractsDir?: string;
+ artifactsDir?: string;
+ compilerSettings?: solc.CompilerSettings;
+ contracts?: string[] | '*';
+}
+
+export interface ContractSourceData {
+ [contractName: string]: ContractSpecificSourceData;
+}
+
+export interface ContractSpecificSourceData {
+ solcVersionRange: string;
+ sourceHash: Buffer;
+ sourceTreeHash: Buffer;
+}
+
+export interface Token {
+ address?: string;
+ name: string;
+ symbol: string;
+ decimals: number;
+ ipfsHash: string;
+ swarmHash: string;
+}
+
+export type DoneCallback = (err?: Error) => void;
diff --git a/packages/sol-compiler/src/utils/utils.ts b/packages/sol-compiler/src/utils/utils.ts
new file mode 100644
index 000000000..4f2de2caa
--- /dev/null
+++ b/packages/sol-compiler/src/utils/utils.ts
@@ -0,0 +1,6 @@
+export const utils = {
+ stringifyWithFormatting(obj: any): string {
+ const stringifiedObj = JSON.stringify(obj, null, '\t');
+ return stringifiedObj;
+ },
+};