Merge pull request #1004 from feuGeneA/sol-doc
[ethereum-types, react-docs, sol-compiler, sol-doc, types, typescript-typings, website] Add new Solidity documentation generation utility
This commit is contained in:
@@ -100,6 +100,7 @@ jobs:
|
||||
- run: yarn wsrun test:circleci @0xproject/order-watcher
|
||||
- run: yarn wsrun test:circleci @0xproject/sol-compiler
|
||||
- run: yarn wsrun test:circleci @0xproject/sol-cov
|
||||
- run: yarn wsrun test:circleci @0xproject/sol-doc
|
||||
- run: yarn wsrun test:circleci @0xproject/sra-report
|
||||
- run: yarn wsrun test:circleci @0xproject/subproviders
|
||||
- run: yarn wsrun test:circleci @0xproject/web3-wrapper
|
||||
@@ -152,6 +153,10 @@ jobs:
|
||||
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-cov/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-doc/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
@@ -218,6 +223,9 @@ jobs:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
|
||||
|
@@ -36,7 +36,8 @@
|
||||
"generate_doc": "node ./packages/monorepo-scripts/lib/doc_generate_and_upload.js",
|
||||
"test:generate_docs:circleci": "for i in ${npm_package_config_packagesWithDocPages}; do yarn generate_doc --package $i --shouldUpload false --isStaging true || break -1; done;",
|
||||
"lint": "wsrun lint $PKG --fast-exit --parallel --exclude-missing",
|
||||
"comment:postinstall": "HACK: For some reason `yarn` is not setting up symlinks properly for order-utils. We temporarily set them manually. Remove this after V2 refactor is complete."
|
||||
"comment:postinstall": "HACK: For some reason `yarn` is not setting up symlink properly for types. We temporarily make it manually. Remove this ASAP!",
|
||||
"postinstall": "shx cp -R node_modules/@0xproject/types packages/website/node_modules/@0xproject; shx cp -R node_modules/@0xproject/types packages/sra-report/node_modules/@0xproject; rimraf node_modules/@0xproject/types; shx ln -s ../../packages/types node_modules/@0xproject/types"
|
||||
},
|
||||
"config": {
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic",
|
||||
|
@@ -325,9 +325,57 @@ export interface ContractNetworkData {
|
||||
constructorArgs: string;
|
||||
}
|
||||
|
||||
export type ParamDescription = string;
|
||||
|
||||
export interface StandardContractOutput {
|
||||
abi: ContractAbi;
|
||||
evm: EvmOutput;
|
||||
devdoc?: DevdocOutput;
|
||||
}
|
||||
|
||||
export interface StandardOutput {
|
||||
errors: SolcError[];
|
||||
sources: {
|
||||
[fileName: string]: {
|
||||
id: number;
|
||||
ast?: object;
|
||||
legacyAST?: object;
|
||||
};
|
||||
};
|
||||
contracts: {
|
||||
[fileName: string]: {
|
||||
[contractName: string]: StandardContractOutput;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type ErrorType =
|
||||
| 'JSONError'
|
||||
| 'IOError'
|
||||
| 'ParserError'
|
||||
| 'DocstringParsingError'
|
||||
| 'SyntaxError'
|
||||
| 'DeclarationError'
|
||||
| 'TypeError'
|
||||
| 'UnimplementedFeatureError'
|
||||
| 'InternalCompilerError'
|
||||
| 'Exception'
|
||||
| 'CompilerError'
|
||||
| 'FatalError'
|
||||
| 'Warning';
|
||||
export type ErrorSeverity = 'error' | 'warning';
|
||||
|
||||
export interface SolcError {
|
||||
sourceLocation?: {
|
||||
file: string;
|
||||
start: number;
|
||||
end: number;
|
||||
};
|
||||
type: ErrorType;
|
||||
component: 'general' | 'ewasm';
|
||||
severity: ErrorSeverity;
|
||||
message: string;
|
||||
formattedMessage?: string;
|
||||
}
|
||||
|
||||
export interface EvmOutput {
|
||||
@@ -340,6 +388,20 @@ export interface EvmBytecodeOutput {
|
||||
sourceMap: string;
|
||||
}
|
||||
|
||||
export interface DevdocOutput {
|
||||
title: string;
|
||||
author: string;
|
||||
methods: {
|
||||
[signature: string]: {
|
||||
details: string;
|
||||
params: {
|
||||
[name: string]: ParamDescription;
|
||||
};
|
||||
return?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface ContractVersionData {
|
||||
compiler: CompilerOpts;
|
||||
sources: {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#### WARNING: Alpha software. Expect things to break when trying to use.
|
||||
|
||||
A full-page React component for rendering beautiful documentation for Solidity and Typescript code generated with [TypeDoc](http://typedoc.org/) or [Doxity](https://github.com/0xproject/doxity).
|
||||
A full-page React component for rendering beautiful documentation for Solidity and Typescript code generated with [TypeDoc](http://typedoc.org/) or [sol-doc](https://github.com/0xProject/0x-monorepo/tree/development/packages/sol-doc).
|
||||
|
||||
<div style="text-align: center;">
|
||||
<img src="https://s3.eu-west-2.amazonaws.com/0x-wiki-images/screenshot.png" style="padding-bottom: 20px; padding-top: 20px;" width="80%" />
|
||||
@@ -47,7 +47,7 @@ Feel free to contribute to these improvements!
|
||||
|
||||
* Allow user to pass in styling for all major elements similar to [Material-UI](http://www.material-ui.com/).
|
||||
* Allow user to define an alternative font and have it change everywhere.
|
||||
* Add source links to Solidity docs (currently unsupported by Doxity).
|
||||
* Add source links to Solidity docs (currently unsupported by solc, which underlies sol-doc).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "React documentation component for rendering TypeDoc & Doxity generated JSON",
|
||||
"description": "React documentation component for rendering TypeDoc & sol-doc generated JSON",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
@@ -34,6 +34,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/react-shared": "^1.0.12",
|
||||
"@0xproject/types": "^1.1.0",
|
||||
"@0xproject/utils": "^1.0.11",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/material-ui": "^0.20.0",
|
||||
|
@@ -2,7 +2,7 @@ import { logUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { CustomType } from '../types';
|
||||
import { CustomType } from '@0xproject/types';
|
||||
|
||||
const STRING_ENUM_CODE_PREFIX = ' strEnum(';
|
||||
|
||||
|
@@ -9,24 +9,23 @@ import {
|
||||
Styles,
|
||||
utils as sharedUtils,
|
||||
} from '@0xproject/react-shared';
|
||||
import {
|
||||
DocAgnosticFormat,
|
||||
Event,
|
||||
ExternalExportToLink,
|
||||
Property,
|
||||
SolidityMethod,
|
||||
TypeDefinitionByName,
|
||||
TypescriptFunction,
|
||||
TypescriptMethod,
|
||||
} from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
import CircularProgress from 'material-ui/CircularProgress';
|
||||
import * as React from 'react';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import {
|
||||
AddressByContractName,
|
||||
DocAgnosticFormat,
|
||||
Event,
|
||||
ExternalExportToLink,
|
||||
Property,
|
||||
SolidityMethod,
|
||||
SupportedDocJson,
|
||||
TypeDefinitionByName,
|
||||
TypescriptFunction,
|
||||
TypescriptMethod,
|
||||
} from '../types';
|
||||
import { AddressByContractName, SupportedDocJson } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { Badge } from './badge';
|
||||
@@ -330,7 +329,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
|
||||
return <div>{externalExports}</div>;
|
||||
}
|
||||
private _renderNetworkBadgesIfExists(sectionName: string): React.ReactNode {
|
||||
if (this.props.docsInfo.type !== SupportedDocJson.Doxity) {
|
||||
if (this.props.docsInfo.type !== SupportedDocJson.SolDoc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { AnchorTitle, colors, HeaderSizes } from '@0xproject/react-shared';
|
||||
import { Event, EventArg } from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Event, EventArg } from '../types';
|
||||
|
||||
import { Type } from './type';
|
||||
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { CustomType, TypeDefinitionByName } from '@0xproject/types';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { CustomType, TypeDefinitionByName } from '../types';
|
||||
|
||||
import { Signature } from './signature';
|
||||
import { Type } from './type';
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { AnchorTitle, HeaderSizes } from '@0xproject/react-shared';
|
||||
import { Property, TypeDefinitionByName } from '@0xproject/types';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Property, TypeDefinitionByName } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { Comment } from './comment';
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Parameter, Type as TypeDef, TypeDefinitionByName, TypeParameter } from '@0xproject/types';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Parameter, Type as TypeDef, TypeDefinitionByName, TypeParameter } from '../types';
|
||||
|
||||
import { Type } from './type';
|
||||
|
||||
|
@@ -1,9 +1,15 @@
|
||||
import { AnchorTitle, colors, HeaderSizes, Styles } from '@0xproject/react-shared';
|
||||
import {
|
||||
Parameter,
|
||||
SolidityMethod,
|
||||
TypeDefinitionByName,
|
||||
TypescriptFunction,
|
||||
TypescriptMethod,
|
||||
} from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptFunction, TypescriptMethod } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { Comment } from './comment';
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { colors } from '@0xproject/react-shared';
|
||||
import { Source } from '@0xproject/types';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Source } from '../types';
|
||||
|
||||
export interface SourceLinkProps {
|
||||
source: Source;
|
||||
sourceUrl: string;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { colors, constants as sharedConstants, utils as sharedUtils } from '@0xproject/react-shared';
|
||||
import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '@0xproject/types';
|
||||
import { errorUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
@@ -6,7 +7,6 @@ import { Link as ScrollLink } from 'react-scroll';
|
||||
import * as ReactTooltip from 'react-tooltip';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { Signature } from './signature';
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import { AnchorTitle, colors, HeaderSizes } from '@0xproject/react-shared';
|
||||
import { CustomType, CustomTypeChild, TypeDefinitionByName, TypeDocTypes } from '@0xproject/types';
|
||||
import { errorUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { CustomType, CustomTypeChild, KindString, TypeDefinitionByName, TypeDocTypes } from '../types';
|
||||
import { KindString } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { Comment } from './comment';
|
||||
|
@@ -1,20 +1,15 @@
|
||||
import { MenuSubsectionsBySection } from '@0xproject/react-shared';
|
||||
import { DocAgnosticFormat, TypeDefinitionByName } from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
ContractsByVersionByNetworkId,
|
||||
DocAgnosticFormat,
|
||||
DocsInfoConfig,
|
||||
DocsMenu,
|
||||
DoxityDocObj,
|
||||
GeneratedDocJson,
|
||||
SectionNameToMarkdownByVersion,
|
||||
SectionsMap,
|
||||
SupportedDocJson,
|
||||
TypeDefinitionByName,
|
||||
} from './types';
|
||||
import { doxityUtils } from './utils/doxity_utils';
|
||||
import { TypeDocUtils } from './utils/typedoc_utils';
|
||||
|
||||
export class DocsInfo {
|
||||
public id: string;
|
||||
@@ -95,12 +90,4 @@ export class DocsInfo {
|
||||
const typeDefinitionByName = _.keyBy(typeDocSection.types, 'name') as any;
|
||||
return typeDefinitionByName;
|
||||
}
|
||||
public convertToDocAgnosticFormat(docObj: DoxityDocObj | GeneratedDocJson): DocAgnosticFormat {
|
||||
if (this.type === SupportedDocJson.Doxity) {
|
||||
return doxityUtils.convertToDocAgnosticFormat(docObj as DoxityDocObj);
|
||||
} else {
|
||||
const typeDocUtils = new TypeDocUtils(docObj as GeneratedDocJson, this);
|
||||
return typeDocUtils.convertToDocAgnosticFormat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
export { DocAgnosticFormat, GeneratedDocJson } from '@0xproject/types';
|
||||
|
||||
// Exported to give users of this library added flexibility if they want to build
|
||||
// a docs page from scratch using the individual components.
|
||||
export { Badge } from './components/badge';
|
||||
@@ -12,17 +14,10 @@ export { Signature } from './components/signature';
|
||||
export { SourceLink } from './components/source_link';
|
||||
export { TypeDefinition } from './components/type_definition';
|
||||
export { Type } from './components/type';
|
||||
export { TypeDocUtils } from './utils/typedoc_utils';
|
||||
|
||||
export { DocsInfo } from './docs_info';
|
||||
|
||||
export {
|
||||
DocsInfoConfig,
|
||||
DocAgnosticFormat,
|
||||
DoxityDocObj,
|
||||
DocsMenu,
|
||||
SupportedDocJson,
|
||||
TypeDocNode,
|
||||
GeneratedDocJson,
|
||||
} from './types';
|
||||
export { DocsInfoConfig, DocsMenu, SupportedDocJson } from './types';
|
||||
|
||||
export { constants } from './utils/constants';
|
||||
|
@@ -22,72 +22,6 @@ export interface SectionsMap {
|
||||
[sectionName: string]: string;
|
||||
}
|
||||
|
||||
export interface TypeDocType {
|
||||
type: TypeDocTypes;
|
||||
value: string;
|
||||
name: string;
|
||||
types: TypeDocType[];
|
||||
typeArguments?: TypeDocType[];
|
||||
declaration: TypeDocNode;
|
||||
elementType?: TypeDocType;
|
||||
indexSignature?: TypeDocNode;
|
||||
elements?: TupleElement[];
|
||||
}
|
||||
|
||||
export interface TupleElement {
|
||||
type: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface TypeDocFlags {
|
||||
isStatic?: boolean;
|
||||
isOptional?: boolean;
|
||||
isPublic?: boolean;
|
||||
isExported?: boolean;
|
||||
}
|
||||
|
||||
export interface TypeDocGroup {
|
||||
title: string;
|
||||
children: number[];
|
||||
}
|
||||
|
||||
export interface TypeDocNode {
|
||||
id?: number;
|
||||
name?: string;
|
||||
kind?: string;
|
||||
defaultValue?: string;
|
||||
kindString?: string;
|
||||
type?: TypeDocType;
|
||||
fileName?: string;
|
||||
line?: number;
|
||||
comment?: TypeDocNode;
|
||||
text?: string;
|
||||
shortText?: string;
|
||||
returns?: string;
|
||||
declaration: TypeDocNode;
|
||||
flags?: TypeDocFlags;
|
||||
indexSignature?: TypeDocNode;
|
||||
signatures?: TypeDocNode[];
|
||||
parameters?: TypeDocNode[];
|
||||
typeParameter?: TypeDocNode[];
|
||||
sources?: TypeDocNode[];
|
||||
children?: TypeDocNode[];
|
||||
groups?: TypeDocGroup[];
|
||||
}
|
||||
|
||||
export enum TypeDocTypes {
|
||||
Intrinsic = 'intrinsic',
|
||||
Reference = 'reference',
|
||||
Array = 'array',
|
||||
StringLiteral = 'stringLiteral',
|
||||
Reflection = 'reflection',
|
||||
Union = 'union',
|
||||
TypeParameter = 'typeParameter',
|
||||
Intersection = 'intersection',
|
||||
Tuple = 'tuple',
|
||||
Unknown = 'unknown',
|
||||
}
|
||||
|
||||
// Exception: We don't make the values uppercase because these KindString's need to
|
||||
// match up those returned by TypeDoc
|
||||
export enum KindString {
|
||||
@@ -103,141 +37,8 @@ export enum KindString {
|
||||
Class = 'Class',
|
||||
}
|
||||
|
||||
export interface DocAgnosticFormat {
|
||||
[sectionName: string]: DocSection;
|
||||
}
|
||||
|
||||
export interface DocSection {
|
||||
comment: string;
|
||||
constructors: Array<TypescriptMethod | SolidityMethod>;
|
||||
methods: Array<TypescriptMethod | SolidityMethod>;
|
||||
properties: Property[];
|
||||
types: CustomType[];
|
||||
functions: TypescriptFunction[];
|
||||
events?: Event[];
|
||||
externalExportToLink?: ExternalExportToLink;
|
||||
}
|
||||
|
||||
export interface TypescriptMethod extends BaseMethod {
|
||||
source?: Source;
|
||||
isStatic?: boolean;
|
||||
typeParameter?: TypeParameter;
|
||||
}
|
||||
|
||||
export interface TypescriptFunction extends BaseFunction {
|
||||
source?: Source;
|
||||
typeParameter?: TypeParameter;
|
||||
callPath: string;
|
||||
}
|
||||
|
||||
export interface SolidityMethod extends BaseMethod {
|
||||
isConstant?: boolean;
|
||||
isPayable?: boolean;
|
||||
}
|
||||
|
||||
export interface Source {
|
||||
fileName: string;
|
||||
line: number;
|
||||
}
|
||||
|
||||
export interface Parameter {
|
||||
name: string;
|
||||
comment: string;
|
||||
isOptional: boolean;
|
||||
type: Type;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export interface TypeParameter {
|
||||
name: string;
|
||||
type?: Type;
|
||||
}
|
||||
|
||||
export interface Type {
|
||||
name: string;
|
||||
typeDocType: TypeDocTypes;
|
||||
value?: string;
|
||||
isExportedClassReference?: boolean;
|
||||
typeArguments?: Type[];
|
||||
elementType?: ElementType;
|
||||
types?: Type[];
|
||||
method?: TypescriptMethod;
|
||||
indexSignature?: IndexSignature;
|
||||
externalLink?: string;
|
||||
tupleElements?: Type[];
|
||||
}
|
||||
|
||||
export interface ElementType {
|
||||
name: string;
|
||||
typeDocType: TypeDocTypes;
|
||||
}
|
||||
|
||||
export interface IndexSignature {
|
||||
keyName: string;
|
||||
keyType: Type;
|
||||
valueName: string;
|
||||
}
|
||||
|
||||
export interface CustomType {
|
||||
name: string;
|
||||
kindString: string;
|
||||
type?: Type;
|
||||
method?: TypescriptMethod;
|
||||
indexSignature?: IndexSignature;
|
||||
defaultValue?: string;
|
||||
comment?: string;
|
||||
children?: CustomTypeChild[];
|
||||
}
|
||||
|
||||
export interface CustomTypeChild {
|
||||
name: string;
|
||||
type?: Type;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
name: string;
|
||||
eventArgs: EventArg[];
|
||||
}
|
||||
|
||||
export interface EventArg {
|
||||
isIndexed: boolean;
|
||||
name: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface Property {
|
||||
name: string;
|
||||
type: Type;
|
||||
source?: Source;
|
||||
comment?: string;
|
||||
callPath?: string;
|
||||
}
|
||||
|
||||
export interface BaseMethod {
|
||||
isConstructor: boolean;
|
||||
name: string;
|
||||
returnComment?: string | undefined;
|
||||
callPath: string;
|
||||
parameters: Parameter[];
|
||||
returnType: Type;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface BaseFunction {
|
||||
name: string;
|
||||
returnComment?: string | undefined;
|
||||
parameters: Parameter[];
|
||||
returnType: Type;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface TypeDefinitionByName {
|
||||
[typeName: string]: CustomType;
|
||||
}
|
||||
|
||||
export enum SupportedDocJson {
|
||||
Doxity = 'DOXITY',
|
||||
SolDoc = 'SOL_DOC',
|
||||
TypeDoc = 'TYPEDOC',
|
||||
}
|
||||
|
||||
@@ -249,40 +50,6 @@ export interface ContractsByVersionByNetworkId {
|
||||
};
|
||||
}
|
||||
|
||||
export interface DoxityDocObj {
|
||||
[contractName: string]: DoxityContractObj;
|
||||
}
|
||||
|
||||
export interface DoxityContractObj {
|
||||
title: string;
|
||||
fileName: string;
|
||||
name: string;
|
||||
abiDocs: DoxityAbiDoc[];
|
||||
}
|
||||
|
||||
export interface DoxityAbiDoc {
|
||||
constant: boolean;
|
||||
inputs: DoxityInput[];
|
||||
name: string;
|
||||
outputs: DoxityOutput[];
|
||||
payable: boolean;
|
||||
type: string;
|
||||
details?: string;
|
||||
return?: string;
|
||||
}
|
||||
|
||||
export interface DoxityOutput {
|
||||
name: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface DoxityInput {
|
||||
name: string;
|
||||
type: string;
|
||||
description: string;
|
||||
indexed?: boolean;
|
||||
}
|
||||
|
||||
export interface AddressByContractName {
|
||||
[contractName: string]: string;
|
||||
}
|
||||
@@ -297,28 +64,3 @@ export enum AbiTypes {
|
||||
Function = 'function',
|
||||
Event = 'event',
|
||||
}
|
||||
|
||||
export interface ExportNameToTypedocNames {
|
||||
[exportName: string]: string[];
|
||||
}
|
||||
|
||||
export interface ExternalTypeToLink {
|
||||
[externalTypeName: string]: string;
|
||||
}
|
||||
|
||||
export interface ExternalExportToLink {
|
||||
[externalExport: string]: string;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
exportPathToTypedocNames: ExportNameToTypedocNames;
|
||||
exportPathOrder: string[];
|
||||
externalTypeToLink: ExternalTypeToLink;
|
||||
externalExportToLink: ExternalExportToLink;
|
||||
}
|
||||
|
||||
export interface GeneratedDocJson {
|
||||
version: string;
|
||||
metadata: Metadata;
|
||||
typedocJson: TypeDocNode;
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ export const constants = {
|
||||
TYPES_SECTION_NAME: 'types',
|
||||
EXTERNAL_EXPORTS_SECTION_NAME: 'external exports',
|
||||
TYPE_TO_SYNTAX: {
|
||||
[SupportedDocJson.Doxity]: 'solidity',
|
||||
[SupportedDocJson.SolDoc]: 'solidity',
|
||||
[SupportedDocJson.TypeDoc]: 'typescript',
|
||||
} as { [supportedDocType: string]: string },
|
||||
};
|
||||
|
@@ -1,176 +0,0 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
AbiTypes,
|
||||
DocAgnosticFormat,
|
||||
DocSection,
|
||||
DoxityAbiDoc,
|
||||
DoxityContractObj,
|
||||
DoxityDocObj,
|
||||
DoxityInput,
|
||||
EventArg,
|
||||
Parameter,
|
||||
Property,
|
||||
SolidityMethod,
|
||||
Type,
|
||||
TypeDocTypes,
|
||||
} from '../types';
|
||||
|
||||
export const doxityUtils = {
|
||||
convertToDocAgnosticFormat(doxityDocObj: DoxityDocObj): DocAgnosticFormat {
|
||||
const docAgnosticFormat: DocAgnosticFormat = {};
|
||||
_.each(doxityDocObj, (doxityContractObj: DoxityContractObj, contractName: string) => {
|
||||
const doxityConstructor = _.find(doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => {
|
||||
return abiDoc.type === AbiTypes.Constructor;
|
||||
});
|
||||
const constructors = [];
|
||||
if (!_.isUndefined(doxityConstructor)) {
|
||||
const constructor = {
|
||||
isConstructor: true,
|
||||
name: doxityContractObj.name,
|
||||
comment: doxityConstructor.details,
|
||||
returnComment: doxityConstructor.return,
|
||||
callPath: '',
|
||||
parameters: doxityUtils._convertParameters(doxityConstructor.inputs),
|
||||
returnType: doxityUtils._convertType(doxityContractObj.name),
|
||||
};
|
||||
constructors.push(constructor);
|
||||
}
|
||||
|
||||
const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>(
|
||||
doxityContractObj.abiDocs,
|
||||
(abiDoc: DoxityAbiDoc) => {
|
||||
return doxityUtils._isMethod(abiDoc);
|
||||
},
|
||||
);
|
||||
const methods: SolidityMethod[] = _.map<DoxityAbiDoc, SolidityMethod>(
|
||||
doxityMethods,
|
||||
(doxityMethod: DoxityAbiDoc) => {
|
||||
const outputs = !_.isUndefined(doxityMethod.outputs) ? doxityMethod.outputs : [];
|
||||
let returnTypeIfExists: Type;
|
||||
if (outputs.length === 0) {
|
||||
// no-op. It's already undefined
|
||||
} else if (outputs.length === 1) {
|
||||
const outputsType = outputs[0].type;
|
||||
returnTypeIfExists = doxityUtils._convertType(outputsType);
|
||||
} else {
|
||||
const outputsType = `[${_.map(outputs, output => output.type).join(', ')}]`;
|
||||
returnTypeIfExists = doxityUtils._convertType(outputsType);
|
||||
}
|
||||
// For ZRXToken, we want to convert it to zrxToken, rather then simply zRXToken
|
||||
const callPath =
|
||||
contractName !== 'ZRXToken'
|
||||
? `${contractName[0].toLowerCase()}${contractName.slice(1)}.`
|
||||
: `${contractName.slice(0, 3).toLowerCase()}${contractName.slice(3)}.`;
|
||||
const method = {
|
||||
isConstructor: false,
|
||||
isConstant: doxityMethod.constant,
|
||||
isPayable: doxityMethod.payable,
|
||||
name: doxityMethod.name,
|
||||
comment: doxityMethod.details,
|
||||
returnComment: doxityMethod.return,
|
||||
callPath,
|
||||
parameters: doxityUtils._convertParameters(doxityMethod.inputs),
|
||||
returnType: returnTypeIfExists,
|
||||
};
|
||||
return method;
|
||||
},
|
||||
);
|
||||
|
||||
const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>(
|
||||
doxityContractObj.abiDocs,
|
||||
(abiDoc: DoxityAbiDoc) => {
|
||||
return doxityUtils._isProperty(abiDoc);
|
||||
},
|
||||
);
|
||||
const properties = _.map<DoxityAbiDoc, Property>(doxityProperties, (doxityProperty: DoxityAbiDoc) => {
|
||||
// We assume that none of our functions return more then a single return value
|
||||
let typeName = doxityProperty.outputs[0].type;
|
||||
if (!_.isEmpty(doxityProperty.inputs)) {
|
||||
// Properties never have more then a single input
|
||||
typeName = `(${doxityProperty.inputs[0].type} => ${typeName})`;
|
||||
}
|
||||
const property = {
|
||||
name: doxityProperty.name,
|
||||
type: doxityUtils._convertType(typeName),
|
||||
comment: doxityProperty.details,
|
||||
};
|
||||
return property;
|
||||
});
|
||||
|
||||
const doxityEvents = _.filter(
|
||||
doxityContractObj.abiDocs,
|
||||
(abiDoc: DoxityAbiDoc) => abiDoc.type === AbiTypes.Event,
|
||||
);
|
||||
const events = _.map(doxityEvents, doxityEvent => {
|
||||
const event = {
|
||||
name: doxityEvent.name,
|
||||
eventArgs: doxityUtils._convertEventArgs(doxityEvent.inputs),
|
||||
};
|
||||
return event;
|
||||
});
|
||||
|
||||
const docSection: DocSection = {
|
||||
comment: doxityContractObj.title,
|
||||
constructors,
|
||||
methods,
|
||||
properties,
|
||||
types: [],
|
||||
functions: [],
|
||||
events,
|
||||
};
|
||||
docAgnosticFormat[contractName] = docSection;
|
||||
});
|
||||
return docAgnosticFormat;
|
||||
},
|
||||
_convertParameters(inputs: DoxityInput[]): Parameter[] {
|
||||
const parameters = _.map(inputs, input => {
|
||||
const parameter = {
|
||||
name: input.name,
|
||||
comment: input.description,
|
||||
isOptional: false,
|
||||
type: doxityUtils._convertType(input.type),
|
||||
};
|
||||
return parameter;
|
||||
});
|
||||
return parameters;
|
||||
},
|
||||
_convertType(typeName: string): Type {
|
||||
const type = {
|
||||
name: typeName,
|
||||
typeDocType: TypeDocTypes.Intrinsic,
|
||||
};
|
||||
return type;
|
||||
},
|
||||
_isMethod(abiDoc: DoxityAbiDoc): boolean {
|
||||
if (abiDoc.type !== AbiTypes.Function) {
|
||||
return false;
|
||||
}
|
||||
const hasInputs = !_.isEmpty(abiDoc.inputs);
|
||||
const hasNamedOutputIfExists = !hasInputs || !_.isEmpty(abiDoc.inputs[0].name);
|
||||
const isNameAllCaps = abiDoc.name === abiDoc.name.toUpperCase();
|
||||
const isMethod = hasNamedOutputIfExists && !isNameAllCaps;
|
||||
return isMethod;
|
||||
},
|
||||
_isProperty(abiDoc: DoxityAbiDoc): boolean {
|
||||
if (abiDoc.type !== AbiTypes.Function) {
|
||||
return false;
|
||||
}
|
||||
const hasInputs = !_.isEmpty(abiDoc.inputs);
|
||||
const hasNamedOutputIfExists = !hasInputs || !_.isEmpty(abiDoc.inputs[0].name);
|
||||
const isNameAllCaps = abiDoc.name === abiDoc.name.toUpperCase();
|
||||
const isProperty = !hasNamedOutputIfExists || isNameAllCaps;
|
||||
return isProperty;
|
||||
},
|
||||
_convertEventArgs(inputs: DoxityInput[]): EventArg[] {
|
||||
const eventArgs = _.map(inputs, input => {
|
||||
const eventArg = {
|
||||
isIndexed: input.indexed,
|
||||
name: input.name,
|
||||
type: doxityUtils._convertType(input.type),
|
||||
};
|
||||
return eventArg;
|
||||
});
|
||||
return eventArgs;
|
||||
},
|
||||
};
|
@@ -1,7 +1,3 @@
|
||||
import { errorUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import {
|
||||
CustomType,
|
||||
CustomTypeChild,
|
||||
@@ -11,7 +7,6 @@ import {
|
||||
ExternalTypeToLink,
|
||||
GeneratedDocJson,
|
||||
IndexSignature,
|
||||
KindString,
|
||||
Parameter,
|
||||
Property,
|
||||
Type,
|
||||
@@ -21,7 +16,12 @@ import {
|
||||
TypeParameter,
|
||||
TypescriptFunction,
|
||||
TypescriptMethod,
|
||||
} from '../types';
|
||||
} from '@0xproject/types';
|
||||
import { errorUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { KindString } from '../types';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
@@ -471,6 +471,8 @@ export class TypeDocUtils {
|
||||
methodIfExists = this._convertMethod(entity.declaration, isConstructor, sectionName);
|
||||
} else if (entity.type === TypeDocTypes.Tuple) {
|
||||
tupleElementsIfExists = _.map(entity.elements, el => {
|
||||
// the following line is required due to an open tslint issue, https://github.com/palantir/tslint/issues/3540
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
return { name: el.name, typeDocType: el.type as TypeDocTypes };
|
||||
});
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ import {
|
||||
} from '@0xproject/sol-resolver';
|
||||
import { fetchAsync, logUtils } from '@0xproject/utils';
|
||||
import chalk from 'chalk';
|
||||
import { CompilerOptions, ContractArtifact, ContractVersionData } from 'ethereum-types';
|
||||
import { CompilerOptions, ContractArtifact, ContractVersionData, StandardOutput } from 'ethereum-types';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as fs from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
@@ -94,7 +94,7 @@ export class Compiler {
|
||||
if (await fsWrapper.doesFileExistAsync(compilerBinFilename)) {
|
||||
solcjs = (await fsWrapper.readFileAsync(compilerBinFilename)).toString();
|
||||
} else {
|
||||
logUtils.log(`Downloading ${fullSolcVersion}...`);
|
||||
logUtils.warn(`Downloading ${fullSolcVersion}...`);
|
||||
const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`;
|
||||
const response = await fetchAsync(url);
|
||||
const SUCCESS_STATUS = 200;
|
||||
@@ -110,6 +110,21 @@ export class Compiler {
|
||||
const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename));
|
||||
return { solcInstance, fullSolcVersion };
|
||||
}
|
||||
private static _addHexPrefixToContractBytecode(compiledContract: solc.StandardContractOutput): void {
|
||||
if (!_.isUndefined(compiledContract.evm)) {
|
||||
if (!_.isUndefined(compiledContract.evm.bytecode) && !_.isUndefined(compiledContract.evm.bytecode.object)) {
|
||||
compiledContract.evm.bytecode.object = ethUtil.addHexPrefix(compiledContract.evm.bytecode.object);
|
||||
}
|
||||
if (
|
||||
!_.isUndefined(compiledContract.evm.deployedBytecode) &&
|
||||
!_.isUndefined(compiledContract.evm.deployedBytecode.object)
|
||||
) {
|
||||
compiledContract.evm.deployedBytecode.object = ethUtil.addHexPrefix(
|
||||
compiledContract.evm.deployedBytecode.object,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Instantiates a new instance of the Compiler class.
|
||||
* @param opts Optional compiler options
|
||||
@@ -144,22 +159,40 @@ export class Compiler {
|
||||
public async compileAsync(): Promise<void> {
|
||||
await createDirIfDoesNotExistAsync(this._artifactsDir);
|
||||
await createDirIfDoesNotExistAsync(SOLC_BIN_DIR);
|
||||
let contractNamesToCompile: string[] = [];
|
||||
await this._compileContractsAsync(this._getContractNamesToCompile(), true);
|
||||
}
|
||||
/**
|
||||
* Compiles Solidity files specified during instantiation, and returns the
|
||||
* compiler output given by solc. Return value is an array of outputs:
|
||||
* Solidity modules are batched together by version required, and each
|
||||
* element of the returned array corresponds to a compiler version, and
|
||||
* each element contains the output for all of the modules compiled with
|
||||
* that version.
|
||||
*/
|
||||
public async getCompilerOutputsAsync(): Promise<StandardOutput[]> {
|
||||
const promisedOutputs = this._compileContractsAsync(this._getContractNamesToCompile(), false);
|
||||
return promisedOutputs;
|
||||
}
|
||||
private _getContractNamesToCompile(): string[] {
|
||||
let contractNamesToCompile;
|
||||
if (this._specifiedContracts === ALL_CONTRACTS_IDENTIFIER) {
|
||||
const allContracts = this._nameResolver.getAll();
|
||||
contractNamesToCompile = _.map(allContracts, contractSource =>
|
||||
path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION),
|
||||
);
|
||||
} else {
|
||||
contractNamesToCompile = this._specifiedContracts;
|
||||
contractNamesToCompile = this._specifiedContracts.map(specifiedContract =>
|
||||
path.basename(specifiedContract, constants.SOLIDITY_FILE_EXTENSION),
|
||||
);
|
||||
}
|
||||
await this._compileContractsAsync(contractNamesToCompile);
|
||||
return contractNamesToCompile;
|
||||
}
|
||||
/**
|
||||
* Compiles contract and saves artifact to artifactsDir.
|
||||
* Compiles contracts, and, if `shouldPersist` is true, saves artifacts to artifactsDir.
|
||||
* @param fileName Name of contract with '.sol' extension.
|
||||
* @return an array of compiler outputs, where each element corresponds to a different version of solc-js.
|
||||
*/
|
||||
private async _compileContractsAsync(contractNames: string[]): Promise<void> {
|
||||
private async _compileContractsAsync(contractNames: string[], shouldPersist: boolean): Promise<StandardOutput[]> {
|
||||
// batch input contracts together based on the version of the compiler that they require.
|
||||
const versionToInputs: VersionToInputs = {};
|
||||
|
||||
@@ -200,10 +233,12 @@ export class Compiler {
|
||||
versionToInputs[solcVersion].contractsToCompile.push(contractSource.path);
|
||||
}
|
||||
|
||||
const compilerOutputs: StandardOutput[] = [];
|
||||
|
||||
const solcVersions = _.keys(versionToInputs);
|
||||
for (const solcVersion of solcVersions) {
|
||||
const input = versionToInputs[solcVersion];
|
||||
logUtils.log(
|
||||
logUtils.warn(
|
||||
`Compiling ${input.contractsToCompile.length} contracts (${
|
||||
input.contractsToCompile
|
||||
}) with Solidity v${solcVersion}...`,
|
||||
@@ -212,18 +247,34 @@ export class Compiler {
|
||||
const { solcInstance, fullSolcVersion } = await Compiler._getSolcAsync(solcVersion);
|
||||
|
||||
const compilerOutput = this._compile(solcInstance, input.standardInput);
|
||||
compilerOutputs.push(compilerOutput);
|
||||
|
||||
for (const contractPath of input.contractsToCompile) {
|
||||
await this._verifyAndPersistCompiledContractAsync(
|
||||
contractPath,
|
||||
contractPathToData[contractPath].currentArtifactIfExists,
|
||||
contractPathToData[contractPath].sourceTreeHashHex,
|
||||
contractPathToData[contractPath].contractName,
|
||||
fullSolcVersion,
|
||||
compilerOutput,
|
||||
);
|
||||
const contractName = contractPathToData[contractPath].contractName;
|
||||
|
||||
const compiledContract = compilerOutput.contracts[contractPath][contractName];
|
||||
if (_.isUndefined(compiledContract)) {
|
||||
throw new Error(
|
||||
`Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`,
|
||||
);
|
||||
}
|
||||
|
||||
Compiler._addHexPrefixToContractBytecode(compiledContract);
|
||||
|
||||
if (shouldPersist) {
|
||||
await this._persistCompiledContractAsync(
|
||||
contractPath,
|
||||
contractPathToData[contractPath].currentArtifactIfExists,
|
||||
contractPathToData[contractPath].sourceTreeHashHex,
|
||||
contractName,
|
||||
fullSolcVersion,
|
||||
compilerOutput,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return compilerOutputs;
|
||||
}
|
||||
private _shouldCompile(contractData: ContractData): boolean {
|
||||
if (_.isUndefined(contractData.currentArtifactIfExists)) {
|
||||
@@ -236,7 +287,7 @@ export class Compiler {
|
||||
return !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange;
|
||||
}
|
||||
}
|
||||
private async _verifyAndPersistCompiledContractAsync(
|
||||
private async _persistCompiledContractAsync(
|
||||
contractPath: string,
|
||||
currentArtifactIfExists: ContractArtifact | void,
|
||||
sourceTreeHashHex: string,
|
||||
@@ -244,32 +295,13 @@ export class Compiler {
|
||||
fullSolcVersion: string,
|
||||
compilerOutput: solc.StandardOutput,
|
||||
): Promise<void> {
|
||||
const compiledData = compilerOutput.contracts[contractPath][contractName];
|
||||
if (_.isUndefined(compiledData)) {
|
||||
throw new Error(
|
||||
`Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`,
|
||||
);
|
||||
}
|
||||
if (!_.isUndefined(compiledData.evm)) {
|
||||
if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) {
|
||||
compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object);
|
||||
}
|
||||
if (
|
||||
!_.isUndefined(compiledData.evm.deployedBytecode) &&
|
||||
!_.isUndefined(compiledData.evm.deployedBytecode.object)
|
||||
) {
|
||||
compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix(
|
||||
compiledData.evm.deployedBytecode.object,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const compiledContract = compilerOutput.contracts[contractPath][contractName];
|
||||
const sourceCodes = _.mapValues(
|
||||
compilerOutput.sources,
|
||||
(_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source,
|
||||
);
|
||||
const contractVersion: ContractVersionData = {
|
||||
compilerOutput: compiledData,
|
||||
compilerOutput: compiledContract,
|
||||
sources: compilerOutput.sources,
|
||||
sourceCodes,
|
||||
sourceTreeHashHex,
|
||||
@@ -299,7 +331,7 @@ export class Compiler {
|
||||
const artifactString = utils.stringifyWithFormatting(newArtifact);
|
||||
const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`;
|
||||
await fsWrapper.writeFileAsync(currentArtifactPath, artifactString);
|
||||
logUtils.log(`${contractName} artifact saved!`);
|
||||
logUtils.warn(`${contractName} artifact saved!`);
|
||||
}
|
||||
private _compile(solcInstance: solc.SolcInstance, standardInput: solc.StandardInput): solc.StandardOutput {
|
||||
const compiled: solc.StandardOutput = JSON.parse(
|
||||
@@ -315,13 +347,13 @@ export class Compiler {
|
||||
if (!_.isEmpty(errors)) {
|
||||
errors.forEach(error => {
|
||||
const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message);
|
||||
logUtils.log(chalk.red(normalizedErrMsg));
|
||||
logUtils.warn(chalk.red(normalizedErrMsg));
|
||||
});
|
||||
throw new Error('Compilation errors encountered');
|
||||
} else {
|
||||
warnings.forEach(warning => {
|
||||
const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message);
|
||||
logUtils.log(chalk.yellow(normalizedWarningMsg));
|
||||
logUtils.warn(chalk.yellow(normalizedWarningMsg));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,28 @@
|
||||
export { Compiler } from './compiler';
|
||||
export {
|
||||
AbiDefinition,
|
||||
CompilerOptions,
|
||||
CompilerSettings,
|
||||
DataItem,
|
||||
DevdocOutput,
|
||||
ErrorSeverity,
|
||||
ErrorType,
|
||||
EventAbi,
|
||||
EventParameter,
|
||||
EvmBytecodeOutput,
|
||||
EvmOutput,
|
||||
FallbackAbi,
|
||||
FunctionAbi,
|
||||
MethodAbi,
|
||||
ConstructorAbi,
|
||||
ConstructorStateMutability,
|
||||
ContractAbi,
|
||||
OutputField,
|
||||
CompilerSettingsMetadata,
|
||||
OptimizerSettings,
|
||||
ParamDescription,
|
||||
SolcError,
|
||||
StandardContractOutput,
|
||||
StandardOutput,
|
||||
StateMutability,
|
||||
} from 'ethereum-types';
|
||||
|
@@ -26,7 +26,7 @@ export async function getContractArtifactIfExistsAsync(
|
||||
contractArtifact = JSON.parse(contractArtifactString);
|
||||
return contractArtifact;
|
||||
} catch (err) {
|
||||
logUtils.log(`Artifact for ${contractName} does not exist`);
|
||||
logUtils.warn(`Artifact for ${contractName} does not exist`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ export async function getContractArtifactIfExistsAsync(
|
||||
*/
|
||||
export async function createDirIfDoesNotExistAsync(dirPath: string): Promise<void> {
|
||||
if (!fsWrapper.doesPathExistSync(dirPath)) {
|
||||
logUtils.log(`Creating directory at ${dirPath}...`);
|
||||
logUtils.warn(`Creating directory at ${dirPath}...`);
|
||||
await fsWrapper.mkdirpAsync(dirPath);
|
||||
}
|
||||
}
|
||||
|
12
packages/sol-doc/CHANGELOG.json
Normal file
12
packages/sol-doc/CHANGELOG.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note":
|
||||
"Utility to generate documentation for Solidity smart contracts, outputting a format compliant with @0xproject/types.DocAgnosticFormat",
|
||||
"pr": 1004
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
0
packages/sol-doc/coverage/.gitkeep
Normal file
0
packages/sol-doc/coverage/.gitkeep
Normal file
49
packages/sol-doc/package.json
Normal file
49
packages/sol-doc/package.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "@0xproject/sol-doc",
|
||||
"version": "1.0.0",
|
||||
"description": "Solidity documentation generator",
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --timeout 6000 --exit",
|
||||
"test:circleci": "yarn test:coverage",
|
||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||
"lint": "tslint --project . --format stylish",
|
||||
"clean": "shx rm -rf lib",
|
||||
"generate-v1-protocol-docs": "(cd ../contracts/src/1.0.0; node ../../../../node_modules/.bin/sol-doc --contracts-dir . --contracts Exchange/Exchange_v1.sol TokenRegistry/TokenRegistry.sol TokenTransferProxy/TokenTransferProxy_v1.sol) > v1.0.0.json",
|
||||
"generate-v2-protocol-docs": "(cd ../contracts/src/2.0.0; node ../../../../node_modules/.bin/sol-doc --contracts-dir . --contracts $(cd protocol; ls -C1 */*.sol */interfaces/*.sol) ) > v2.0.0.json",
|
||||
"deploy-v2-protocol-docs": "aws --profile 0xproject s3 cp --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json v2.0.0.json s3://staging-doc-jsons/contracts/",
|
||||
"deploy-v1-protocol-docs": "aws --profile 0xproject s3 cp --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json v1.0.0.json s3://staging-doc-jsons/contracts/"
|
||||
},
|
||||
"bin": {
|
||||
"sol-doc": "bin/sol-doc.js"
|
||||
},
|
||||
"repository": "https://github.com/0xProject/0x-monorepo.git",
|
||||
"author": "F. Eugene Aumson",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@0xproject/sol-compiler": "^1.1.5",
|
||||
"@0xproject/types": "^1.1.1",
|
||||
"@0xproject/utils": "^1.0.11",
|
||||
"ethereum-types": "^1.0.4",
|
||||
"lodash": "^4.17.10",
|
||||
"yargs": "^12.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^1.0.7",
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.2",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^5.2.0",
|
||||
"shx": "^0.2.2",
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
28
packages/sol-doc/src/cli.ts
Normal file
28
packages/sol-doc/src/cli.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'source-map-support/register';
|
||||
import * as yargs from 'yargs';
|
||||
|
||||
import { logUtils } from '@0xproject/utils';
|
||||
|
||||
import { generateSolDocAsync } from './solidity_doc_generator';
|
||||
|
||||
const JSON_TAB_WIDTH = 4;
|
||||
|
||||
(async () => {
|
||||
const argv = yargs
|
||||
.option('contracts-dir', {
|
||||
type: 'string',
|
||||
description: 'path of contracts directory to compile',
|
||||
})
|
||||
.option('contracts', {
|
||||
type: 'string',
|
||||
description: 'comma separated list of contracts to compile',
|
||||
})
|
||||
.demandOption('contracts-dir')
|
||||
.array('contracts')
|
||||
.help().argv;
|
||||
const doc = await generateSolDocAsync(argv.contractsDir, argv.contracts);
|
||||
process.stdout.write(JSON.stringify(doc, null, JSON_TAB_WIDTH));
|
||||
})().catch(err => {
|
||||
logUtils.warn(err);
|
||||
process.exit(1);
|
||||
});
|
1
packages/sol-doc/src/index.ts
Normal file
1
packages/sol-doc/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { generateSolDocAsync } from './solidity_doc_generator';
|
306
packages/sol-doc/src/solidity_doc_generator.ts
Normal file
306
packages/sol-doc/src/solidity_doc_generator.ts
Normal file
@@ -0,0 +1,306 @@
|
||||
import * as path from 'path';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
AbiDefinition,
|
||||
ConstructorAbi,
|
||||
DataItem,
|
||||
DevdocOutput,
|
||||
EventAbi,
|
||||
EventParameter,
|
||||
FallbackAbi,
|
||||
MethodAbi,
|
||||
StandardContractOutput,
|
||||
} from 'ethereum-types';
|
||||
|
||||
import { Compiler, CompilerOptions } from '@0xproject/sol-compiler';
|
||||
import {
|
||||
DocAgnosticFormat,
|
||||
DocSection,
|
||||
Event,
|
||||
EventArg,
|
||||
Parameter,
|
||||
SolidityMethod,
|
||||
Type,
|
||||
TypeDocTypes,
|
||||
} from '@0xproject/types';
|
||||
|
||||
/**
|
||||
* Invoke the Solidity compiler and transform its ABI and devdoc outputs into a
|
||||
* JSON format easily consumed by documentation rendering tools.
|
||||
* @param contractsToDocument list of contracts for which to generate doc objects
|
||||
* @param contractsDir the directory in which to find the `contractsToCompile` as well as their dependencies.
|
||||
* @return doc object for use with documentation generation tools.
|
||||
*/
|
||||
export async function generateSolDocAsync(
|
||||
contractsDir: string,
|
||||
contractsToDocument?: string[],
|
||||
): Promise<DocAgnosticFormat> {
|
||||
const docWithDependencies: DocAgnosticFormat = {};
|
||||
const compilerOptions = _makeCompilerOptions(contractsDir, contractsToDocument);
|
||||
const compiler = new Compiler(compilerOptions);
|
||||
const compilerOutputs = await compiler.getCompilerOutputsAsync();
|
||||
for (const compilerOutput of compilerOutputs) {
|
||||
const contractFileNames = _.keys(compilerOutput.contracts);
|
||||
for (const contractFileName of contractFileNames) {
|
||||
const contractNameToOutput = compilerOutput.contracts[contractFileName];
|
||||
|
||||
const contractNames = _.keys(contractNameToOutput);
|
||||
for (const contractName of contractNames) {
|
||||
const compiledContract = contractNameToOutput[contractName];
|
||||
if (_.isUndefined(compiledContract.abi)) {
|
||||
throw new Error('compiled contract did not contain ABI output');
|
||||
}
|
||||
docWithDependencies[contractName] = _genDocSection(compiledContract, contractName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let doc: DocAgnosticFormat = {};
|
||||
if (_.isUndefined(contractsToDocument) || contractsToDocument.length === 0) {
|
||||
doc = docWithDependencies;
|
||||
} else {
|
||||
for (const contractToDocument of contractsToDocument) {
|
||||
const contractBasename = path.basename(contractToDocument);
|
||||
const contractName =
|
||||
contractBasename.lastIndexOf('.sol') === -1
|
||||
? contractBasename
|
||||
: contractBasename.substring(0, contractBasename.lastIndexOf('.sol'));
|
||||
doc[contractName] = docWithDependencies[contractName];
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
function _makeCompilerOptions(contractsDir: string, contractsToCompile?: string[]): CompilerOptions {
|
||||
const compilerOptions: CompilerOptions = {
|
||||
contractsDir,
|
||||
contracts: '*',
|
||||
compilerSettings: {
|
||||
outputSelection: {
|
||||
['*']: {
|
||||
['*']: ['abi', 'devdoc'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const shouldOverrideCatchAllContractsConfig = !_.isUndefined(contractsToCompile) && contractsToCompile.length > 0;
|
||||
if (shouldOverrideCatchAllContractsConfig) {
|
||||
compilerOptions.contracts = contractsToCompile;
|
||||
}
|
||||
|
||||
return compilerOptions;
|
||||
}
|
||||
|
||||
function _genDocSection(compiledContract: StandardContractOutput, contractName: string): DocSection {
|
||||
const docSection: DocSection = {
|
||||
comment: _.isUndefined(compiledContract.devdoc) ? '' : compiledContract.devdoc.title,
|
||||
constructors: [],
|
||||
methods: [],
|
||||
properties: [],
|
||||
types: [],
|
||||
functions: [],
|
||||
events: [],
|
||||
};
|
||||
|
||||
for (const abiDefinition of compiledContract.abi) {
|
||||
switch (abiDefinition.type) {
|
||||
case 'constructor':
|
||||
docSection.constructors.push(_genConstructorDoc(contractName, abiDefinition, compiledContract.devdoc));
|
||||
break;
|
||||
case 'event':
|
||||
(docSection.events as Event[]).push(_genEventDoc(abiDefinition));
|
||||
// note that we're not sending devdoc to _genEventDoc().
|
||||
// that's because the type of the events array doesn't have any fields for documentation!
|
||||
break;
|
||||
case 'function':
|
||||
case 'fallback':
|
||||
docSection.methods.push(_genMethodDoc(abiDefinition, compiledContract.devdoc));
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`unknown and unsupported AbiDefinition type '${(abiDefinition as AbiDefinition).type}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return docSection;
|
||||
}
|
||||
|
||||
function _genConstructorDoc(
|
||||
contractName: string,
|
||||
abiDefinition: ConstructorAbi,
|
||||
devdocIfExists: DevdocOutput | undefined,
|
||||
): SolidityMethod {
|
||||
const { parameters, methodSignature } = _genMethodParamsDoc('', abiDefinition.inputs, devdocIfExists);
|
||||
|
||||
const comment = _devdocMethodDetailsIfExist(methodSignature, devdocIfExists);
|
||||
|
||||
const constructorDoc: SolidityMethod = {
|
||||
isConstructor: true,
|
||||
name: contractName,
|
||||
callPath: '',
|
||||
parameters,
|
||||
returnType: { name: contractName, typeDocType: TypeDocTypes.Reference }, // sad we have to specify this
|
||||
isConstant: false,
|
||||
isPayable: abiDefinition.payable,
|
||||
comment,
|
||||
};
|
||||
|
||||
return constructorDoc;
|
||||
}
|
||||
|
||||
function _devdocMethodDetailsIfExist(
|
||||
methodSignature: string,
|
||||
devdocIfExists: DevdocOutput | undefined,
|
||||
): string | undefined {
|
||||
let details;
|
||||
if (!_.isUndefined(devdocIfExists)) {
|
||||
const devdocMethodsIfExist = devdocIfExists.methods;
|
||||
if (!_.isUndefined(devdocMethodsIfExist)) {
|
||||
const devdocMethodIfExists = devdocMethodsIfExist[methodSignature];
|
||||
if (!_.isUndefined(devdocMethodIfExists)) {
|
||||
const devdocMethodDetailsIfExist = devdocMethodIfExists.details;
|
||||
if (!_.isUndefined(devdocMethodDetailsIfExist)) {
|
||||
details = devdocMethodDetailsIfExist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
function _genMethodDoc(
|
||||
abiDefinition: MethodAbi | FallbackAbi,
|
||||
devdocIfExists: DevdocOutput | undefined,
|
||||
): SolidityMethod {
|
||||
const name = abiDefinition.type === 'fallback' ? '' : abiDefinition.name;
|
||||
|
||||
const { parameters, methodSignature } =
|
||||
abiDefinition.type === 'fallback'
|
||||
? { parameters: [], methodSignature: `${name}()` }
|
||||
: _genMethodParamsDoc(name, abiDefinition.inputs, devdocIfExists);
|
||||
|
||||
const comment = _devdocMethodDetailsIfExist(methodSignature, devdocIfExists);
|
||||
|
||||
const returnType =
|
||||
abiDefinition.type === 'fallback'
|
||||
? { name: '', typeDocType: TypeDocTypes.Intrinsic }
|
||||
: _genMethodReturnTypeDoc(abiDefinition.outputs, methodSignature, devdocIfExists);
|
||||
|
||||
const returnComment =
|
||||
_.isUndefined(devdocIfExists) || _.isUndefined(devdocIfExists.methods[methodSignature])
|
||||
? undefined
|
||||
: devdocIfExists.methods[methodSignature].return;
|
||||
|
||||
const isConstant = abiDefinition.type === 'fallback' ? true : abiDefinition.constant;
|
||||
|
||||
const methodDoc: SolidityMethod = {
|
||||
isConstructor: false,
|
||||
name,
|
||||
callPath: '',
|
||||
parameters,
|
||||
returnType,
|
||||
returnComment,
|
||||
isConstant,
|
||||
isPayable: abiDefinition.payable,
|
||||
comment,
|
||||
};
|
||||
return methodDoc;
|
||||
}
|
||||
|
||||
function _genEventDoc(abiDefinition: EventAbi): Event {
|
||||
const eventDoc: Event = {
|
||||
name: abiDefinition.name,
|
||||
eventArgs: _genEventArgsDoc(abiDefinition.inputs, undefined),
|
||||
};
|
||||
return eventDoc;
|
||||
}
|
||||
|
||||
function _genEventArgsDoc(args: EventParameter[], devdocIfExists: DevdocOutput | undefined): EventArg[] {
|
||||
const eventArgsDoc: EventArg[] = [];
|
||||
|
||||
for (const arg of args) {
|
||||
const name = arg.name;
|
||||
|
||||
const type: Type = {
|
||||
name: arg.type,
|
||||
typeDocType: TypeDocTypes.Intrinsic,
|
||||
};
|
||||
|
||||
const eventArgDoc: EventArg = {
|
||||
isIndexed: arg.indexed,
|
||||
name,
|
||||
type,
|
||||
};
|
||||
|
||||
eventArgsDoc.push(eventArgDoc);
|
||||
}
|
||||
return eventArgsDoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract documentation for each method parameter from @param params.
|
||||
*/
|
||||
function _genMethodParamsDoc(
|
||||
name: string,
|
||||
abiParams: DataItem[],
|
||||
devdocIfExists: DevdocOutput | undefined,
|
||||
): { parameters: Parameter[]; methodSignature: string } {
|
||||
const parameters: Parameter[] = [];
|
||||
for (const abiParam of abiParams) {
|
||||
const parameter: Parameter = {
|
||||
name: abiParam.name,
|
||||
comment: '',
|
||||
isOptional: false, // Unsupported in Solidity, until resolution of https://github.com/ethereum/solidity/issues/232
|
||||
type: { name: abiParam.type, typeDocType: TypeDocTypes.Intrinsic },
|
||||
};
|
||||
parameters.push(parameter);
|
||||
}
|
||||
|
||||
const methodSignature = `${name}(${abiParams
|
||||
.map(abiParam => {
|
||||
return abiParam.type;
|
||||
})
|
||||
.join(',')})`;
|
||||
|
||||
if (!_.isUndefined(devdocIfExists)) {
|
||||
const devdocMethodIfExists = devdocIfExists.methods[methodSignature];
|
||||
if (!_.isUndefined(devdocMethodIfExists)) {
|
||||
const devdocParamsIfExist = devdocMethodIfExists.params;
|
||||
if (!_.isUndefined(devdocParamsIfExist)) {
|
||||
for (const parameter of parameters) {
|
||||
parameter.comment = devdocParamsIfExist[parameter.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { parameters, methodSignature };
|
||||
}
|
||||
|
||||
function _genMethodReturnTypeDoc(
|
||||
outputs: DataItem[],
|
||||
methodSignature: string,
|
||||
devdocIfExists: DevdocOutput | undefined,
|
||||
): Type {
|
||||
const methodReturnTypeDoc: Type = {
|
||||
name: '',
|
||||
typeDocType: TypeDocTypes.Intrinsic,
|
||||
tupleElements: undefined,
|
||||
};
|
||||
if (outputs.length > 1) {
|
||||
methodReturnTypeDoc.typeDocType = TypeDocTypes.Tuple;
|
||||
methodReturnTypeDoc.tupleElements = [];
|
||||
for (const output of outputs) {
|
||||
methodReturnTypeDoc.tupleElements.push({ name: output.type, typeDocType: TypeDocTypes.Intrinsic });
|
||||
}
|
||||
} else if (outputs.length === 1) {
|
||||
methodReturnTypeDoc.typeDocType = TypeDocTypes.Intrinsic;
|
||||
methodReturnTypeDoc.name = outputs[0].type;
|
||||
}
|
||||
return methodReturnTypeDoc;
|
||||
}
|
7
packages/sol-doc/test/fixtures/contracts/MultipleReturnValues.sol
vendored
Normal file
7
packages/sol-doc/test/fixtures/contracts/MultipleReturnValues.sol
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
contract MultipleReturnValues {
|
||||
function methodWithMultipleReturnValues() public pure returns(int, int) {
|
||||
return (0, 0);
|
||||
}
|
||||
}
|
40
packages/sol-doc/test/fixtures/contracts/NatspecEverything.sol
vendored
Normal file
40
packages/sol-doc/test/fixtures/contracts/NatspecEverything.sol
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
/// @title Contract Title
|
||||
/// @dev This is a very long documentation comment at the contract level.
|
||||
/// It actually spans multiple lines, too.
|
||||
contract NatspecEverything {
|
||||
int d;
|
||||
|
||||
/// @dev Constructor @dev
|
||||
/// @param p Constructor @param
|
||||
constructor(int p) public { d = p; }
|
||||
|
||||
/// @notice publicMethod @notice
|
||||
/// @dev publicMethod @dev
|
||||
/// @param p publicMethod @param
|
||||
/// @return publicMethod @return
|
||||
function publicMethod(int p) public pure returns(int r) { return p; }
|
||||
|
||||
/// @dev Fallback @dev
|
||||
function () public {}
|
||||
|
||||
/// @notice externalMethod @notice
|
||||
/// @dev externalMethod @dev
|
||||
/// @param p externalMethod @param
|
||||
/// @return externalMethod @return
|
||||
function externalMethod(int p) external pure returns(int r) { return p; }
|
||||
|
||||
/// @dev Here is a really long developer documentation comment, which spans
|
||||
/// multiple lines, for the purposes of making sure that broken lines are
|
||||
/// consolidated into one devdoc comment.
|
||||
function methodWithLongDevdoc(int p) public pure returns(int) { return p; }
|
||||
|
||||
/// @dev AnEvent @dev
|
||||
/// @param p on this event is an integer.
|
||||
event AnEvent(int p);
|
||||
|
||||
/// @dev methodWithSolhintDirective @dev
|
||||
// solhint-disable no-empty-blocks
|
||||
function methodWithSolhintDirective() public pure {}
|
||||
}
|
115
packages/sol-doc/test/fixtures/contracts/TokenTransferProxy.sol
vendored
Normal file
115
packages/sol-doc/test/fixtures/contracts/TokenTransferProxy.sol
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.14;
|
||||
|
||||
import { Ownable } from "zeppelin-solidity/contracts/ownership/Ownable.sol";
|
||||
import { ERC20 as Token } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
/// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance.
|
||||
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
|
||||
contract TokenTransferProxy is Ownable {
|
||||
|
||||
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||
modifier onlyAuthorized {
|
||||
require(authorized[msg.sender]);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier targetAuthorized(address target) {
|
||||
require(authorized[target]);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier targetNotAuthorized(address target) {
|
||||
require(!authorized[target]);
|
||||
_;
|
||||
}
|
||||
|
||||
mapping (address => bool) public authorized;
|
||||
address[] public authorities;
|
||||
|
||||
event LogAuthorizedAddressAdded(address indexed target, address indexed caller);
|
||||
event LogAuthorizedAddressRemoved(address indexed target, address indexed caller);
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
public
|
||||
onlyOwner
|
||||
targetNotAuthorized(target)
|
||||
{
|
||||
authorized[target] = true;
|
||||
authorities.push(target);
|
||||
LogAuthorizedAddressAdded(target, msg.sender);
|
||||
}
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
public
|
||||
onlyOwner
|
||||
targetAuthorized(target)
|
||||
{
|
||||
delete authorized[target];
|
||||
for (uint i = 0; i < authorities.length; i++) {
|
||||
if (authorities[i] == target) {
|
||||
authorities[i] = authorities[authorities.length - 1];
|
||||
authorities.length -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogAuthorizedAddressRemoved(target, msg.sender);
|
||||
}
|
||||
|
||||
/// @dev Calls into ERC20 Token contract, invoking transferFrom.
|
||||
/// @param token Address of token to transfer.
|
||||
/// @param from Address to transfer token from.
|
||||
/// @param to Address to transfer token to.
|
||||
/// @param value Amount of token to transfer.
|
||||
/// @return Success of transfer.
|
||||
function transferFrom(
|
||||
address token,
|
||||
address from,
|
||||
address to,
|
||||
uint value)
|
||||
public
|
||||
onlyAuthorized
|
||||
returns (bool)
|
||||
{
|
||||
return Token(token).transferFrom(from, to, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public constant functions
|
||||
*/
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses()
|
||||
public
|
||||
constant
|
||||
returns (address[])
|
||||
{
|
||||
return authorities;
|
||||
}
|
||||
}
|
100
packages/sol-doc/test/fixtures/contracts/TokenTransferProxyNoDevdoc.sol
vendored
Normal file
100
packages/sol-doc/test/fixtures/contracts/TokenTransferProxyNoDevdoc.sol
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.14;
|
||||
|
||||
import { Ownable } from "zeppelin-solidity/contracts/ownership/Ownable.sol";
|
||||
import { ERC20 as Token } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
contract TokenTransferProxyNoDevdoc is Ownable {
|
||||
|
||||
modifier onlyAuthorized {
|
||||
require(authorized[msg.sender]);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier targetAuthorized(address target) {
|
||||
require(authorized[target]);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier targetNotAuthorized(address target) {
|
||||
require(!authorized[target]);
|
||||
_;
|
||||
}
|
||||
|
||||
mapping (address => bool) public authorized;
|
||||
address[] public authorities;
|
||||
|
||||
event LogAuthorizedAddressAdded(address indexed target, address indexed caller);
|
||||
event LogAuthorizedAddressRemoved(address indexed target, address indexed caller);
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
function addAuthorizedAddress(address target)
|
||||
public
|
||||
onlyOwner
|
||||
targetNotAuthorized(target)
|
||||
{
|
||||
authorized[target] = true;
|
||||
authorities.push(target);
|
||||
LogAuthorizedAddressAdded(target, msg.sender);
|
||||
}
|
||||
|
||||
function removeAuthorizedAddress(address target)
|
||||
public
|
||||
onlyOwner
|
||||
targetAuthorized(target)
|
||||
{
|
||||
delete authorized[target];
|
||||
for (uint i = 0; i < authorities.length; i++) {
|
||||
if (authorities[i] == target) {
|
||||
authorities[i] = authorities[authorities.length - 1];
|
||||
authorities.length -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogAuthorizedAddressRemoved(target, msg.sender);
|
||||
}
|
||||
|
||||
function transferFrom(
|
||||
address token,
|
||||
address from,
|
||||
address to,
|
||||
uint value)
|
||||
public
|
||||
onlyAuthorized
|
||||
returns (bool)
|
||||
{
|
||||
return Token(token).transferFrom(from, to, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public constant functions
|
||||
*/
|
||||
|
||||
function getAuthorizedAddresses()
|
||||
public
|
||||
constant
|
||||
returns (address[])
|
||||
{
|
||||
return authorities;
|
||||
}
|
||||
}
|
237
packages/sol-doc/test/solidity_doc_generator_test.ts
Normal file
237
packages/sol-doc/test/solidity_doc_generator_test.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { DocAgnosticFormat, Event, SolidityMethod } from '@0xproject/types';
|
||||
|
||||
import { generateSolDocAsync } from '../src/solidity_doc_generator';
|
||||
|
||||
import { chaiSetup } from './util/chai_setup';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('#SolidityDocGenerator', () => {
|
||||
it('should generate a doc object that matches the devdoc-free TokenTransferProxy fixture', async () => {
|
||||
const doc = await generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, [
|
||||
'TokenTransferProxyNoDevdoc',
|
||||
]);
|
||||
expect(doc).to.not.be.undefined();
|
||||
|
||||
verifyTokenTransferProxyABIIsDocumented(doc, 'TokenTransferProxyNoDevdoc');
|
||||
});
|
||||
const docPromises: Array<Promise<DocAgnosticFormat>> = [
|
||||
generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`),
|
||||
generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, []),
|
||||
];
|
||||
docPromises.forEach(docPromise => {
|
||||
it('should generate a doc object that matches the TokenTransferProxy fixture with its dependencies', async () => {
|
||||
const doc = await docPromise;
|
||||
expect(doc).to.not.be.undefined();
|
||||
|
||||
verifyTokenTransferProxyAndDepsABIsAreDocumented(doc, 'TokenTransferProxy');
|
||||
|
||||
let addAuthorizedAddressMethod: SolidityMethod | undefined;
|
||||
for (const method of doc.TokenTransferProxy.methods) {
|
||||
if (method.name === 'addAuthorizedAddress') {
|
||||
addAuthorizedAddressMethod = method;
|
||||
}
|
||||
}
|
||||
const tokenTransferProxyAddAuthorizedAddressComment = 'Authorizes an address.';
|
||||
expect((addAuthorizedAddressMethod as SolidityMethod).comment).to.equal(
|
||||
tokenTransferProxyAddAuthorizedAddressComment,
|
||||
);
|
||||
|
||||
const expectedParamComment = 'Address to authorize.';
|
||||
expect((addAuthorizedAddressMethod as SolidityMethod).parameters[0].comment).to.equal(expectedParamComment);
|
||||
});
|
||||
});
|
||||
it('should generate a doc object that matches the TokenTransferProxy fixture', async () => {
|
||||
const doc: DocAgnosticFormat = await generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, [
|
||||
'TokenTransferProxy',
|
||||
]);
|
||||
verifyTokenTransferProxyABIIsDocumented(doc, 'TokenTransferProxy');
|
||||
});
|
||||
describe('when processing all the permutations of devdoc stuff that we use in our contracts', () => {
|
||||
let doc: DocAgnosticFormat;
|
||||
before(async () => {
|
||||
doc = await generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, ['NatspecEverything']);
|
||||
expect(doc).to.not.be.undefined();
|
||||
expect(doc.NatspecEverything).to.not.be.undefined();
|
||||
});
|
||||
it('should emit the contract @title as its comment', () => {
|
||||
expect(doc.NatspecEverything.comment).to.equal('Contract Title');
|
||||
});
|
||||
describe('should emit public method documentation for', () => {
|
||||
let methodDoc: SolidityMethod;
|
||||
before(() => {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
methodDoc = doc.NatspecEverything.methods.find(method => {
|
||||
return method.name === 'publicMethod';
|
||||
}) as SolidityMethod;
|
||||
if (_.isUndefined(methodDoc)) {
|
||||
throw new Error('publicMethod not found');
|
||||
}
|
||||
});
|
||||
it('method name', () => {
|
||||
expect(methodDoc.name).to.equal('publicMethod');
|
||||
});
|
||||
it('method comment', () => {
|
||||
expect(methodDoc.comment).to.equal('publicMethod @dev');
|
||||
});
|
||||
it('parameter name', () => {
|
||||
expect(methodDoc.parameters[0].name).to.equal('p');
|
||||
});
|
||||
it('parameter comment', () => {
|
||||
expect(methodDoc.parameters[0].comment).to.equal('publicMethod @param');
|
||||
});
|
||||
it('return type', () => {
|
||||
expect(methodDoc.returnType.name).to.equal('int256');
|
||||
});
|
||||
it('return comment', () => {
|
||||
expect(methodDoc.returnComment).to.equal('publicMethod @return');
|
||||
});
|
||||
});
|
||||
describe('should emit external method documentation for', () => {
|
||||
let methodDoc: SolidityMethod;
|
||||
before(() => {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
methodDoc = doc.NatspecEverything.methods.find(method => {
|
||||
return method.name === 'externalMethod';
|
||||
}) as SolidityMethod;
|
||||
if (_.isUndefined(methodDoc)) {
|
||||
throw new Error('externalMethod not found');
|
||||
}
|
||||
});
|
||||
it('method name', () => {
|
||||
expect(methodDoc.name).to.equal('externalMethod');
|
||||
});
|
||||
it('method comment', () => {
|
||||
expect(methodDoc.comment).to.equal('externalMethod @dev');
|
||||
});
|
||||
it('parameter name', () => {
|
||||
expect(methodDoc.parameters[0].name).to.equal('p');
|
||||
});
|
||||
it('parameter comment', () => {
|
||||
expect(methodDoc.parameters[0].comment).to.equal('externalMethod @param');
|
||||
});
|
||||
it('return type', () => {
|
||||
expect(methodDoc.returnType.name).to.equal('int256');
|
||||
});
|
||||
it('return comment', () => {
|
||||
expect(methodDoc.returnComment).to.equal('externalMethod @return');
|
||||
});
|
||||
});
|
||||
it('should not truncate a multi-line devdoc comment', () => {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const methodDoc: SolidityMethod = doc.NatspecEverything.methods.find(method => {
|
||||
return method.name === 'methodWithLongDevdoc';
|
||||
}) as SolidityMethod;
|
||||
if (_.isUndefined(methodDoc)) {
|
||||
throw new Error('methodWithLongDevdoc not found');
|
||||
}
|
||||
expect(methodDoc.comment).to.equal(
|
||||
'Here is a really long developer documentation comment, which spans multiple lines, for the purposes of making sure that broken lines are consolidated into one devdoc comment.',
|
||||
);
|
||||
});
|
||||
describe('should emit event documentation for', () => {
|
||||
let eventDoc: Event;
|
||||
before(() => {
|
||||
eventDoc = (doc.NatspecEverything.events as Event[])[0];
|
||||
});
|
||||
it('event name', () => {
|
||||
expect(eventDoc.name).to.equal('AnEvent');
|
||||
});
|
||||
it('parameter name', () => {
|
||||
expect(eventDoc.eventArgs[0].name).to.equal('p');
|
||||
});
|
||||
});
|
||||
it('should not let solhint directives obscure natspec content', () => {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const methodDoc: SolidityMethod = doc.NatspecEverything.methods.find(method => {
|
||||
return method.name === 'methodWithSolhintDirective';
|
||||
}) as SolidityMethod;
|
||||
if (_.isUndefined(methodDoc)) {
|
||||
throw new Error('methodWithSolhintDirective not found');
|
||||
}
|
||||
expect(methodDoc.comment).to.equal('methodWithSolhintDirective @dev');
|
||||
});
|
||||
});
|
||||
it('should document a method that returns multiple values', async () => {
|
||||
const doc = await generateSolDocAsync(`${__dirname}/../../test/fixtures/contracts`, ['MultipleReturnValues']);
|
||||
expect(doc.MultipleReturnValues).to.not.be.undefined();
|
||||
expect(doc.MultipleReturnValues.methods).to.not.be.undefined();
|
||||
let methodWithMultipleReturnValues: SolidityMethod | undefined;
|
||||
for (const method of doc.MultipleReturnValues.methods) {
|
||||
if (method.name === 'methodWithMultipleReturnValues') {
|
||||
methodWithMultipleReturnValues = method;
|
||||
}
|
||||
}
|
||||
if (_.isUndefined(methodWithMultipleReturnValues)) {
|
||||
throw new Error('method should not be undefined');
|
||||
}
|
||||
const returnType = methodWithMultipleReturnValues.returnType;
|
||||
expect(returnType.typeDocType).to.equal('tuple');
|
||||
if (_.isUndefined(returnType.tupleElements)) {
|
||||
throw new Error('returnType.tupleElements should not be undefined');
|
||||
}
|
||||
expect(returnType.tupleElements.length).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
||||
function verifyTokenTransferProxyABIIsDocumented(doc: DocAgnosticFormat, contractName: string): void {
|
||||
expect(doc[contractName]).to.not.be.undefined();
|
||||
expect(doc[contractName].constructors).to.not.be.undefined();
|
||||
const tokenTransferProxyConstructorCount = 0;
|
||||
const tokenTransferProxyMethodCount = 8;
|
||||
const tokenTransferProxyEventCount = 3;
|
||||
expect(doc[contractName].constructors.length).to.equal(tokenTransferProxyConstructorCount);
|
||||
expect(doc[contractName].methods.length).to.equal(tokenTransferProxyMethodCount);
|
||||
const events = doc[contractName].events;
|
||||
if (_.isUndefined(events)) {
|
||||
throw new Error('events should never be undefined');
|
||||
}
|
||||
expect(events.length).to.equal(tokenTransferProxyEventCount);
|
||||
}
|
||||
|
||||
function verifyTokenTransferProxyAndDepsABIsAreDocumented(doc: DocAgnosticFormat, contractName: string): void {
|
||||
verifyTokenTransferProxyABIIsDocumented(doc, contractName);
|
||||
|
||||
expect(doc.ERC20).to.not.be.undefined();
|
||||
expect(doc.ERC20.constructors).to.not.be.undefined();
|
||||
expect(doc.ERC20.methods).to.not.be.undefined();
|
||||
const erc20ConstructorCount = 0;
|
||||
const erc20MethodCount = 6;
|
||||
const erc20EventCount = 2;
|
||||
expect(doc.ERC20.constructors.length).to.equal(erc20ConstructorCount);
|
||||
expect(doc.ERC20.methods.length).to.equal(erc20MethodCount);
|
||||
if (_.isUndefined(doc.ERC20.events)) {
|
||||
throw new Error('events should never be undefined');
|
||||
}
|
||||
expect(doc.ERC20.events.length).to.equal(erc20EventCount);
|
||||
|
||||
expect(doc.ERC20Basic).to.not.be.undefined();
|
||||
expect(doc.ERC20Basic.constructors).to.not.be.undefined();
|
||||
expect(doc.ERC20Basic.methods).to.not.be.undefined();
|
||||
const erc20BasicConstructorCount = 0;
|
||||
const erc20BasicMethodCount = 3;
|
||||
const erc20BasicEventCount = 1;
|
||||
expect(doc.ERC20Basic.constructors.length).to.equal(erc20BasicConstructorCount);
|
||||
expect(doc.ERC20Basic.methods.length).to.equal(erc20BasicMethodCount);
|
||||
if (_.isUndefined(doc.ERC20Basic.events)) {
|
||||
throw new Error('events should never be undefined');
|
||||
}
|
||||
expect(doc.ERC20Basic.events.length).to.equal(erc20BasicEventCount);
|
||||
|
||||
let addAuthorizedAddressMethod: SolidityMethod | undefined;
|
||||
for (const method of doc[contractName].methods) {
|
||||
if (method.name === 'addAuthorizedAddress') {
|
||||
addAuthorizedAddressMethod = method;
|
||||
}
|
||||
}
|
||||
expect(
|
||||
addAuthorizedAddressMethod,
|
||||
`method addAuthorizedAddress not found in ${JSON.stringify(doc[contractName].methods)}`,
|
||||
).to.not.be.undefined();
|
||||
}
|
13
packages/sol-doc/test/util/chai_setup.ts
Normal file
13
packages/sol-doc/test/util/chai_setup.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as chai from 'chai';
|
||||
import chaiAsPromised = require('chai-as-promised');
|
||||
import ChaiBigNumber = require('chai-bignumber');
|
||||
import * as dirtyChai from 'dirty-chai';
|
||||
|
||||
export const chaiSetup = {
|
||||
configure(): void {
|
||||
chai.config.includeStack = true;
|
||||
chai.use(ChaiBigNumber());
|
||||
chai.use(dirtyChai);
|
||||
chai.use(chaiAsPromised);
|
||||
},
|
||||
};
|
8
packages/sol-doc/tsconfig.json
Normal file
8
packages/sol-doc/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*"]
|
||||
}
|
3
packages/sol-doc/tslint.json
Normal file
3
packages/sol-doc/tslint.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["@0xproject/tslint-config"]
|
||||
}
|
@@ -158,6 +158,7 @@ export class Handler {
|
||||
if (_.isUndefined(takerTokenIfExists)) {
|
||||
throw new Error(`Unsupported asset type: ${takerTokenSymbol}`);
|
||||
}
|
||||
|
||||
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(ASSET_AMOUNT, makerTokenIfExists.decimals);
|
||||
const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(ASSET_AMOUNT, takerTokenIfExists.decimals);
|
||||
const makerAssetData = assetDataUtils.encodeERC20AssetData(makerTokenIfExists.address);
|
||||
|
@@ -1,3 +1,5 @@
|
||||
// tslint:disable:max-file-line-count
|
||||
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
|
||||
@@ -373,3 +375,226 @@ export interface PagedRequestOpts {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
}
|
||||
|
||||
export interface TypeDocType {
|
||||
type: TypeDocTypes;
|
||||
value: string;
|
||||
name: string;
|
||||
types: TypeDocType[];
|
||||
typeArguments?: TypeDocType[];
|
||||
declaration: TypeDocNode;
|
||||
elementType?: TypeDocType;
|
||||
indexSignature?: TypeDocNode;
|
||||
elements?: TupleElement[];
|
||||
}
|
||||
|
||||
export interface TupleElement {
|
||||
type: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface TypeDocNode {
|
||||
id?: number;
|
||||
name?: string;
|
||||
kind?: string;
|
||||
defaultValue?: string;
|
||||
kindString?: string;
|
||||
type?: TypeDocType;
|
||||
fileName?: string;
|
||||
line?: number;
|
||||
comment?: TypeDocNode;
|
||||
text?: string;
|
||||
shortText?: string;
|
||||
returns?: string;
|
||||
declaration: TypeDocNode;
|
||||
flags?: TypeDocFlags;
|
||||
indexSignature?: TypeDocNode;
|
||||
signatures?: TypeDocNode[];
|
||||
parameters?: TypeDocNode[];
|
||||
typeParameter?: TypeDocNode[];
|
||||
sources?: TypeDocNode[];
|
||||
children?: TypeDocNode[];
|
||||
groups?: TypeDocGroup[];
|
||||
}
|
||||
|
||||
export interface TypeDocFlags {
|
||||
isStatic?: boolean;
|
||||
isOptional?: boolean;
|
||||
isPublic?: boolean;
|
||||
isExported?: boolean;
|
||||
}
|
||||
|
||||
export interface TypeDocGroup {
|
||||
title: string;
|
||||
children: number[];
|
||||
}
|
||||
|
||||
export enum TypeDocTypes {
|
||||
Intrinsic = 'intrinsic',
|
||||
Reference = 'reference',
|
||||
Array = 'array',
|
||||
StringLiteral = 'stringLiteral',
|
||||
Reflection = 'reflection',
|
||||
Union = 'union',
|
||||
TypeParameter = 'typeParameter',
|
||||
Intersection = 'intersection',
|
||||
Tuple = 'tuple',
|
||||
Unknown = 'unknown',
|
||||
}
|
||||
|
||||
export interface CustomTypeChild {
|
||||
name: string;
|
||||
type?: Type;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
name: string;
|
||||
eventArgs: EventArg[];
|
||||
}
|
||||
|
||||
export interface EventArg {
|
||||
isIndexed: boolean;
|
||||
name: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface Property {
|
||||
name: string;
|
||||
type: Type;
|
||||
source?: Source;
|
||||
comment?: string;
|
||||
callPath?: string;
|
||||
}
|
||||
|
||||
export interface BaseMethod {
|
||||
isConstructor: boolean;
|
||||
name: string;
|
||||
returnComment?: string | undefined;
|
||||
callPath: string;
|
||||
parameters: Parameter[];
|
||||
returnType: Type;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface BaseFunction {
|
||||
name: string;
|
||||
returnComment?: string | undefined;
|
||||
parameters: Parameter[];
|
||||
returnType: Type;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface TypeDefinitionByName {
|
||||
[typeName: string]: CustomType;
|
||||
}
|
||||
|
||||
export interface DocAgnosticFormat {
|
||||
[sectionName: string]: DocSection;
|
||||
}
|
||||
|
||||
export interface DocSection {
|
||||
comment: string;
|
||||
constructors: Array<TypescriptMethod | SolidityMethod>;
|
||||
methods: Array<TypescriptMethod | SolidityMethod>;
|
||||
properties: Property[];
|
||||
types: CustomType[];
|
||||
functions: TypescriptFunction[];
|
||||
events?: Event[];
|
||||
externalExportToLink?: ExternalExportToLink;
|
||||
}
|
||||
|
||||
export interface TypescriptMethod extends BaseMethod {
|
||||
source?: Source;
|
||||
isStatic?: boolean;
|
||||
typeParameter?: TypeParameter;
|
||||
}
|
||||
|
||||
export interface TypescriptFunction extends BaseFunction {
|
||||
source?: Source;
|
||||
typeParameter?: TypeParameter;
|
||||
callPath: string;
|
||||
}
|
||||
|
||||
export interface SolidityMethod extends BaseMethod {
|
||||
isConstant?: boolean;
|
||||
isPayable?: boolean;
|
||||
}
|
||||
|
||||
export interface Source {
|
||||
fileName: string;
|
||||
line: number;
|
||||
}
|
||||
|
||||
export interface Parameter {
|
||||
name: string;
|
||||
comment: string;
|
||||
isOptional: boolean;
|
||||
type: Type;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
export interface TypeParameter {
|
||||
name: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface Type {
|
||||
name: string;
|
||||
typeDocType: TypeDocTypes;
|
||||
value?: string;
|
||||
isExportedClassReference?: boolean;
|
||||
typeArguments?: Type[];
|
||||
elementType?: ElementType;
|
||||
types?: Type[];
|
||||
method?: TypescriptMethod;
|
||||
indexSignature?: IndexSignature;
|
||||
externalLink?: string;
|
||||
tupleElements?: Type[];
|
||||
}
|
||||
|
||||
export interface ElementType {
|
||||
name: string;
|
||||
typeDocType: TypeDocTypes;
|
||||
}
|
||||
|
||||
export interface IndexSignature {
|
||||
keyName: string;
|
||||
keyType: Type;
|
||||
valueName: string;
|
||||
}
|
||||
|
||||
export interface CustomType {
|
||||
name: string;
|
||||
kindString: string;
|
||||
type?: Type;
|
||||
method?: TypescriptMethod;
|
||||
indexSignature?: IndexSignature;
|
||||
defaultValue?: string;
|
||||
comment?: string;
|
||||
children?: CustomTypeChild[];
|
||||
}
|
||||
export interface GeneratedDocJson {
|
||||
version: string;
|
||||
metadata: Metadata;
|
||||
typedocJson: TypeDocNode;
|
||||
}
|
||||
|
||||
export interface ExportNameToTypedocNames {
|
||||
[exportName: string]: string[];
|
||||
}
|
||||
|
||||
export interface ExternalTypeToLink {
|
||||
[externalTypeName: string]: string;
|
||||
}
|
||||
|
||||
export interface ExternalExportToLink {
|
||||
[externalExport: string]: string;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
exportPathToTypedocNames: ExportNameToTypedocNames;
|
||||
exportPathOrder: string[];
|
||||
externalTypeToLink: ExternalTypeToLink;
|
||||
externalExportToLink: ExternalExportToLink;
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
declare module 'solc' {
|
||||
export { ErrorType, ErrorSeverity, SolcError, StandardContractOutput, StandardOutput } from 'ethereum-types';
|
||||
import { SolcError } from 'ethereum-types';
|
||||
export interface ContractCompilationResult {
|
||||
srcmap: string;
|
||||
srcmapRuntime: string;
|
||||
@@ -87,62 +89,6 @@ declare module 'solc' {
|
||||
};
|
||||
settings: CompilerSettings;
|
||||
}
|
||||
export type ErrorType =
|
||||
| 'JSONError'
|
||||
| 'IOError'
|
||||
| 'ParserError'
|
||||
| 'DocstringParsingError'
|
||||
| 'SyntaxError'
|
||||
| 'DeclarationError'
|
||||
| 'TypeError'
|
||||
| 'UnimplementedFeatureError'
|
||||
| 'InternalCompilerError'
|
||||
| 'Exception'
|
||||
| 'CompilerError'
|
||||
| 'FatalError'
|
||||
| 'Warning';
|
||||
export type ErrorSeverity = 'error' | 'warning';
|
||||
export interface Error {
|
||||
sourceLocation?: {
|
||||
file: string;
|
||||
start: number;
|
||||
end: number;
|
||||
};
|
||||
type: ErrorType;
|
||||
component: 'general' | 'ewasm';
|
||||
severity: ErrorSeverity;
|
||||
message: string;
|
||||
formattedMessage?: string;
|
||||
}
|
||||
import { ContractAbi } from 'ethereum-types';
|
||||
export interface StandardContractOutput {
|
||||
abi: ContractAbi;
|
||||
evm: {
|
||||
bytecode: {
|
||||
object: string;
|
||||
sourceMap: string;
|
||||
};
|
||||
deployedBytecode: {
|
||||
object: string;
|
||||
sourceMap: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
export interface StandardOutput {
|
||||
errors: Error[];
|
||||
sources: {
|
||||
[fileName: string]: {
|
||||
id: number;
|
||||
ast?: object;
|
||||
legacyAST?: object;
|
||||
};
|
||||
};
|
||||
contracts: {
|
||||
[fileName: string]: {
|
||||
[contractName: string]: StandardContractOutput;
|
||||
};
|
||||
};
|
||||
}
|
||||
export interface SolcInstance {
|
||||
compile(
|
||||
sources: InputSources,
|
||||
@@ -151,6 +97,9 @@ declare module 'solc' {
|
||||
): CompilationResult;
|
||||
compileStandardWrapper(input: string, findImports: (importPath: string) => ImportContents): string;
|
||||
}
|
||||
export function loadRemoteVersion(versionName: string, cb: (err: Error | null, res?: SolcInstance) => void): void;
|
||||
export function loadRemoteVersion(
|
||||
versionName: string,
|
||||
cb: (err: SolcError | null, res?: SolcInstance) => void,
|
||||
): void;
|
||||
export function setupMethods(solcBin: any): SolcInstance;
|
||||
}
|
||||
|
@@ -1,8 +1 @@
|
||||
Welcome to the [0x smart contracts](https://github.com/0xProject/contracts) documentation! This documentation is intended for dApp developers who want to integrate 0x exchange functionality directly into their own smart contracts.
|
||||
|
||||
### Helpful wiki articles:
|
||||
|
||||
* [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
|
||||
* [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
|
||||
* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
|
||||
* [0x protocol message format](https://0xproject.com/wiki#Message-Format)
|
||||
Welcome to the [0x smart contracts](https://github.com/0xProject/0x-monorepo/tree/development/packages/contracts) documentation! This documentation is intended for dApp developers who want to integrate 0x exchange functionality directly into their own smart contracts.
|
||||
|
6
packages/website/md/docs/smart_contracts/2.0.0/introduction.md
vendored
Normal file
6
packages/website/md/docs/smart_contracts/2.0.0/introduction.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
Welcome to the [0x smart contracts](https://github.com/0xProject/0x-monorepo/tree/development/packages/contracts) documentation! This documentation is intended for dApp developers who want to integrate 0x exchange functionality directly into their own smart contracts.
|
||||
|
||||
### Helpful wiki articles:
|
||||
|
||||
* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
|
||||
* [0x Protocol Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md)
|
@@ -11,29 +11,28 @@ import { Translate } from 'ts/utils/translate';
|
||||
|
||||
/* tslint:disable:no-var-requires */
|
||||
const IntroMarkdownV1 = require('md/docs/smart_contracts/1.0.0/introduction');
|
||||
const IntroMarkdownV2 = require('md/docs/smart_contracts/2.0.0/introduction');
|
||||
/* tslint:enable:no-var-requires */
|
||||
|
||||
const docsInfoConfig: DocsInfoConfig = {
|
||||
id: DocPackages.SmartContracts,
|
||||
packageName: 'contracts',
|
||||
type: SupportedDocJson.Doxity,
|
||||
type: SupportedDocJson.SolDoc,
|
||||
displayName: '0x Smart Contracts',
|
||||
packageUrl: 'https://github.com/0xProject/contracts',
|
||||
markdownMenu: {
|
||||
introduction: [Sections.Introduction],
|
||||
contracts: [Sections.Exchange, Sections.TokenRegistry, Sections.ZRXToken, Sections.TokenTransferProxy],
|
||||
},
|
||||
sectionNameToMarkdownByVersion: {
|
||||
'0.0.1': {
|
||||
[Sections.Introduction]: IntroMarkdownV1,
|
||||
},
|
||||
'2.0.0': {
|
||||
[Sections.Introduction]: IntroMarkdownV2,
|
||||
},
|
||||
},
|
||||
markdownSections: {
|
||||
Introduction: Sections.Introduction,
|
||||
Exchange: Sections.Exchange,
|
||||
TokenTransferProxy: Sections.TokenTransferProxy,
|
||||
TokenRegistry: Sections.TokenRegistry,
|
||||
ZRXToken: Sections.ZRXToken,
|
||||
},
|
||||
contractsByVersionByNetworkId: {
|
||||
'1.0.0': {
|
||||
|
@@ -1,4 +1,11 @@
|
||||
import { DocAgnosticFormat, DocsInfo, Documentation } from '@0xproject/react-docs';
|
||||
import {
|
||||
DocAgnosticFormat,
|
||||
DocsInfo,
|
||||
Documentation,
|
||||
GeneratedDocJson,
|
||||
SupportedDocJson,
|
||||
TypeDocUtils,
|
||||
} from '@0xproject/react-docs';
|
||||
import findVersions = require('find-versions');
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
@@ -128,7 +135,22 @@ export class DocPage extends React.Component<DocPageProps, DocPageState> {
|
||||
|
||||
const versionFilePathToFetch = versionToFilePath[versionToFetch];
|
||||
const versionDocObj = await docUtils.getJSONDocFileAsync(versionFilePathToFetch, docBucketRoot);
|
||||
const docAgnosticFormat = this.props.docsInfo.convertToDocAgnosticFormat(versionDocObj);
|
||||
let docAgnosticFormat;
|
||||
if (this.props.docsInfo.type === SupportedDocJson.TypeDoc) {
|
||||
docAgnosticFormat = new TypeDocUtils(
|
||||
versionDocObj as GeneratedDocJson,
|
||||
this.props.docsInfo,
|
||||
).convertToDocAgnosticFormat();
|
||||
} else if (this.props.docsInfo.type === SupportedDocJson.SolDoc) {
|
||||
// documenting solidity.
|
||||
docAgnosticFormat = versionDocObj as DocAgnosticFormat;
|
||||
// HACK: need to modify docsInfo like convertToDocAgnosticFormat() would do
|
||||
this.props.docsInfo.menu.Contracts = [];
|
||||
_.each(docAgnosticFormat, (docObj, contractName) => {
|
||||
this.props.docsInfo.sections[contractName] = contractName;
|
||||
this.props.docsInfo.menu.Contracts.push(contractName);
|
||||
});
|
||||
}
|
||||
|
||||
if (!this._isUnmounted) {
|
||||
this.setState({
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { DoxityDocObj, GeneratedDocJson } from '@0xproject/react-docs';
|
||||
import { DocAgnosticFormat, GeneratedDocJson } from '@0xproject/react-docs';
|
||||
import { fetchAsync, logUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
import { S3FileObject, VersionToFilePath } from 'ts/types';
|
||||
@@ -70,7 +70,7 @@ export const docUtils = {
|
||||
});
|
||||
return versionFilePaths;
|
||||
},
|
||||
async getJSONDocFileAsync(filePath: string, s3DocJsonRoot: string): Promise<GeneratedDocJson | DoxityDocObj> {
|
||||
async getJSONDocFileAsync(filePath: string, s3DocJsonRoot: string): Promise<GeneratedDocJson | DocAgnosticFormat> {
|
||||
const endpoint = `${s3DocJsonRoot}/${filePath}`;
|
||||
const response = await fetchAsync(endpoint);
|
||||
if (response.status !== 200) {
|
||||
|
Reference in New Issue
Block a user