aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml8
-rw-r--r--package.json3
-rw-r--r--packages/connect/CHANGELOG.json9
-rw-r--r--packages/connect/src/http_client.ts2
-rw-r--r--packages/connect/test/http_client_test.ts6
-rw-r--r--packages/ethereum-types/src/index.ts62
-rw-r--r--packages/order-utils/CHANGELOG.json10
-rw-r--r--packages/order-utils/src/signature_utils.ts4
-rw-r--r--packages/react-docs/README.md4
-rw-r--r--packages/react-docs/package.json3
-rw-r--r--packages/react-docs/src/components/custom_enum.tsx2
-rw-r--r--packages/react-docs/src/components/documentation.tsx19
-rw-r--r--packages/react-docs/src/components/event_definition.tsx2
-rw-r--r--packages/react-docs/src/components/interface.tsx3
-rw-r--r--packages/react-docs/src/components/property_block.tsx2
-rw-r--r--packages/react-docs/src/components/signature.tsx3
-rw-r--r--packages/react-docs/src/components/signature_block.tsx8
-rw-r--r--packages/react-docs/src/components/source_link.tsx3
-rw-r--r--packages/react-docs/src/components/type.tsx2
-rw-r--r--packages/react-docs/src/components/type_definition.tsx3
-rw-r--r--packages/react-docs/src/docs_info.ts15
-rw-r--r--packages/react-docs/src/index.ts13
-rw-r--r--packages/react-docs/src/types.ts260
-rw-r--r--packages/react-docs/src/utils/constants.ts2
-rw-r--r--packages/react-docs/src/utils/doxity_utils.ts176
-rw-r--r--packages/react-docs/src/utils/typedoc_utils.ts14
-rw-r--r--packages/sol-compiler/src/compiler.ts114
-rw-r--r--packages/sol-compiler/src/index.ts20
-rw-r--r--packages/sol-compiler/src/utils/compiler.ts4
-rw-r--r--packages/sol-doc/CHANGELOG.json12
-rwxr-xr-xpackages/sol-doc/bin/sol-doc.js2
-rw-r--r--packages/sol-doc/coverage/.gitkeep0
-rw-r--r--packages/sol-doc/package.json49
-rw-r--r--packages/sol-doc/src/cli.ts28
-rw-r--r--packages/sol-doc/src/index.ts1
-rw-r--r--packages/sol-doc/src/solidity_doc_generator.ts306
-rw-r--r--packages/sol-doc/test/fixtures/contracts/MultipleReturnValues.sol7
-rw-r--r--packages/sol-doc/test/fixtures/contracts/NatspecEverything.sol40
-rw-r--r--packages/sol-doc/test/fixtures/contracts/TokenTransferProxy.sol115
-rw-r--r--packages/sol-doc/test/fixtures/contracts/TokenTransferProxyNoDevdoc.sol100
-rw-r--r--packages/sol-doc/test/solidity_doc_generator_test.ts237
-rw-r--r--packages/sol-doc/test/util/chai_setup.ts13
-rw-r--r--packages/sol-doc/tsconfig.json8
-rw-r--r--packages/sol-doc/tslint.json3
-rw-r--r--packages/sra-spec/package.json4
-rw-r--r--packages/sra-spec/src/api.ts2
-rw-r--r--packages/sra-spec/src/examples/relayerApiAssetDataPairsResponse.ts7
-rw-r--r--packages/sra-spec/src/examples/relayerApiOrder.ts7
-rw-r--r--packages/sra-spec/src/examples/relayerApiOrderConfigPayload.ts7
-rw-r--r--packages/sra-spec/src/examples/relayerApiOrderbookResponse.ts14
-rw-r--r--packages/sra-spec/src/examples/relayerApiOrdersResponse.ts7
-rw-r--r--packages/sra-spec/src/examples/signedOrder.ts5
-rw-r--r--packages/sra-spec/src/md/introduction.md6
-rw-r--r--packages/testnet-faucets/src/ts/handler.ts1
-rw-r--r--packages/types/src/index.ts225
-rw-r--r--packages/typescript-typings/types/solc/index.d.ts63
-rw-r--r--packages/website/md/docs/connect/2.0.0/introduction.md2
-rw-r--r--packages/website/md/docs/contract_wrappers/introduction.md2
-rw-r--r--packages/website/md/docs/json_schemas/1.0.0/introduction.md2
-rw-r--r--packages/website/md/docs/smart_contracts/1.0.0/introduction.md9
-rw-r--r--packages/website/md/docs/smart_contracts/2.0.0/introduction.md6
-rw-r--r--packages/website/public/images/coinbase_wallet_logo.pngbin0 -> 103648 bytes
-rw-r--r--packages/website/ts/blockchain.ts2
-rw-r--r--packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx4
-rw-r--r--packages/website/ts/components/portal/portal.tsx2
-rw-r--r--packages/website/ts/components/relayer_index/relayer_index.tsx6
-rw-r--r--packages/website/ts/components/wallet/body_overlay.tsx6
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.ts11
-rw-r--r--packages/website/ts/pages/about/about.tsx2
-rw-r--r--packages/website/ts/pages/documentation/doc_page.tsx26
-rw-r--r--packages/website/ts/types.ts2
-rw-r--r--packages/website/ts/utils/constants.ts6
-rw-r--r--packages/website/ts/utils/doc_utils.ts4
-rw-r--r--packages/website/ts/utils/utils.ts10
-rw-r--r--yarn.lock55
75 files changed, 1539 insertions, 663 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 537b19348..2231ae796 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -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
@@ -153,6 +154,10 @@ jobs:
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:
- ~/repo/packages/sra-report/coverage/lcov.info
@@ -220,6 +225,9 @@ jobs:
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
+ - coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
+ - restore_cache:
+ keys:
- coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
diff --git a/package.json b/package.json
index 61223aa78..cf5f247d6 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/packages/connect/CHANGELOG.json b/packages/connect/CHANGELOG.json
index 9de956d4d..4106be881 100644
--- a/packages/connect/CHANGELOG.json
+++ b/packages/connect/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "3.0.0",
+ "changes": [
+ {
+ "note": "Change /order_config request to a POST instead of GET",
+ "pr": 1091
+ }
+ ]
+ },
+ {
"timestamp": 1537907159,
"version": "2.0.4",
"changes": [
diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts
index 8a68d6c23..bbd0d2042 100644
--- a/packages/connect/src/http_client.ts
+++ b/packages/connect/src/http_client.ts
@@ -149,7 +149,7 @@ export class HttpClient implements Client {
params: requestOpts,
payload: request,
};
- const responseJson = await this._requestAsync('/order_config', HttpRequestType.Get, httpRequestOpts);
+ const responseJson = await this._requestAsync('/order_config', HttpRequestType.Post, httpRequestOpts);
const fees = relayerResponseJsonParsers.parseOrderConfigResponseJson(responseJson);
return fees;
}
diff --git a/packages/connect/test/http_client_test.ts b/packages/connect/test/http_client_test.ts
index 83b77021a..e9fc9372e 100644
--- a/packages/connect/test/http_client_test.ts
+++ b/packages/connect/test/http_client_test.ts
@@ -148,12 +148,12 @@ describe('HttpClient', () => {
};
const url = `${relayUrl}/order_config`;
it('gets order config', async () => {
- fetchMock.get(url, orderConfigResponseJSON);
+ fetchMock.post(url, orderConfigResponseJSON);
const fees = await relayerClient.getOrderConfigAsync(request);
expect(fees).to.be.deep.equal(orderConfigResponse);
});
it('does not mutate input', async () => {
- fetchMock.get(url, orderConfigResponseJSON);
+ fetchMock.post(url, orderConfigResponseJSON);
const makerAssetAmountBefore = request.makerAssetAmount;
const takerAssetAmountBefore = request.takerAssetAmount;
const expirationTimeSecondsBefore = request.expirationTimeSeconds;
@@ -163,7 +163,7 @@ describe('HttpClient', () => {
expect(expirationTimeSecondsBefore).to.be.deep.equal(request.expirationTimeSeconds);
});
it('throws an error for invalid JSON response', async () => {
- fetchMock.get(url, { test: 'dummy' });
+ fetchMock.post(url, { test: 'dummy' });
expect(relayerClient.getOrderConfigAsync(request)).to.be.rejected();
});
});
diff --git a/packages/ethereum-types/src/index.ts b/packages/ethereum-types/src/index.ts
index a3ff2fddb..a92dbdd1b 100644
--- a/packages/ethereum-types/src/index.ts
+++ b/packages/ethereum-types/src/index.ts
@@ -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: {
diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json
index 1162bbc83..31ba68e23 100644
--- a/packages/order-utils/CHANGELOG.json
+++ b/packages/order-utils/CHANGELOG.json
@@ -1,5 +1,15 @@
[
{
+ "version": "1.0.6",
+ "changes": [
+ {
+ "note":
+ "Add signerAddress normalization to `isValidECSignature` to avoid `invalid address recovery` error if caller supplies a checksummed address",
+ "pr": 1096
+ }
+ ]
+ },
+ {
"timestamp": 1537907159,
"version": "1.0.5",
"changes": [
diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts
index c0c9e71a7..3b656d3fc 100644
--- a/packages/order-utils/src/signature_utils.ts
+++ b/packages/order-utils/src/signature_utils.ts
@@ -174,6 +174,7 @@ export const signatureUtils = {
assert.isHexString('data', data);
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
assert.isETHAddressHex('signerAddress', signerAddress);
+ const normalizedSignerAddress = signerAddress.toLowerCase();
const msgHashBuff = ethUtil.toBuffer(data);
try {
@@ -184,7 +185,8 @@ export const signatureUtils = {
ethUtil.toBuffer(signature.s),
);
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
- return retrievedAddress === signerAddress;
+ const normalizedRetrievedAddress = retrievedAddress.toLowerCase();
+ return normalizedRetrievedAddress === normalizedSignerAddress;
} catch (err) {
return false;
}
diff --git a/packages/react-docs/README.md b/packages/react-docs/README.md
index 5d56207de..51e949967 100644
--- a/packages/react-docs/README.md
+++ b/packages/react-docs/README.md
@@ -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
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index be80f8028..aea186f6a 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -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",
diff --git a/packages/react-docs/src/components/custom_enum.tsx b/packages/react-docs/src/components/custom_enum.tsx
index c4252d9e2..fa7c43146 100644
--- a/packages/react-docs/src/components/custom_enum.tsx
+++ b/packages/react-docs/src/components/custom_enum.tsx
@@ -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(';
diff --git a/packages/react-docs/src/components/documentation.tsx b/packages/react-docs/src/components/documentation.tsx
index 9d9b5141a..3cd14923c 100644
--- a/packages/react-docs/src/components/documentation.tsx
+++ b/packages/react-docs/src/components/documentation.tsx
@@ -9,24 +9,23 @@ import {
Styles,
utils as sharedUtils,
} from '@0xproject/react-shared';
-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';
+} 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, 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;
}
diff --git a/packages/react-docs/src/components/event_definition.tsx b/packages/react-docs/src/components/event_definition.tsx
index 6cb80c6b0..37236275b 100644
--- a/packages/react-docs/src/components/event_definition.tsx
+++ b/packages/react-docs/src/components/event_definition.tsx
@@ -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';
diff --git a/packages/react-docs/src/components/interface.tsx b/packages/react-docs/src/components/interface.tsx
index 93b10e96d..9f0800d71 100644
--- a/packages/react-docs/src/components/interface.tsx
+++ b/packages/react-docs/src/components/interface.tsx
@@ -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';
diff --git a/packages/react-docs/src/components/property_block.tsx b/packages/react-docs/src/components/property_block.tsx
index f181e21d2..8434e8682 100644
--- a/packages/react-docs/src/components/property_block.tsx
+++ b/packages/react-docs/src/components/property_block.tsx
@@ -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';
diff --git a/packages/react-docs/src/components/signature.tsx b/packages/react-docs/src/components/signature.tsx
index 4f10f4665..a690a1f03 100644
--- a/packages/react-docs/src/components/signature.tsx
+++ b/packages/react-docs/src/components/signature.tsx
@@ -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';
diff --git a/packages/react-docs/src/components/signature_block.tsx b/packages/react-docs/src/components/signature_block.tsx
index 05145dc23..1ea0ea28c 100644
--- a/packages/react-docs/src/components/signature_block.tsx
+++ b/packages/react-docs/src/components/signature_block.tsx
@@ -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';
diff --git a/packages/react-docs/src/components/source_link.tsx b/packages/react-docs/src/components/source_link.tsx
index c60435ea6..3096ad8d5 100644
--- a/packages/react-docs/src/components/source_link.tsx
+++ b/packages/react-docs/src/components/source_link.tsx
@@ -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;
diff --git a/packages/react-docs/src/components/type.tsx b/packages/react-docs/src/components/type.tsx
index 5f7601ce1..156a3496d 100644
--- a/packages/react-docs/src/components/type.tsx
+++ b/packages/react-docs/src/components/type.tsx
@@ -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';
diff --git a/packages/react-docs/src/components/type_definition.tsx b/packages/react-docs/src/components/type_definition.tsx
index 8d1f88490..09cb3ff74 100644
--- a/packages/react-docs/src/components/type_definition.tsx
+++ b/packages/react-docs/src/components/type_definition.tsx
@@ -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';
diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts
index dec44458d..6355a2f88 100644
--- a/packages/react-docs/src/docs_info.ts
+++ b/packages/react-docs/src/docs_info.ts
@@ -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();
- }
- }
}
diff --git a/packages/react-docs/src/index.ts b/packages/react-docs/src/index.ts
index e4424f679..f9382940c 100644
--- a/packages/react-docs/src/index.ts
+++ b/packages/react-docs/src/index.ts
@@ -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';
diff --git a/packages/react-docs/src/types.ts b/packages/react-docs/src/types.ts
index 29f5664f5..153448513 100644
--- a/packages/react-docs/src/types.ts
+++ b/packages/react-docs/src/types.ts
@@ -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;
-}
diff --git a/packages/react-docs/src/utils/constants.ts b/packages/react-docs/src/utils/constants.ts
index 0b08f2c3e..b5b6cc00d 100644
--- a/packages/react-docs/src/utils/constants.ts
+++ b/packages/react-docs/src/utils/constants.ts
@@ -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 },
};
diff --git a/packages/react-docs/src/utils/doxity_utils.ts b/packages/react-docs/src/utils/doxity_utils.ts
deleted file mode 100644
index 6815daa0c..000000000
--- a/packages/react-docs/src/utils/doxity_utils.ts
+++ /dev/null
@@ -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;
- },
-};
diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts
index e3e9c11fb..19605d497 100644
--- a/packages/react-docs/src/utils/typedoc_utils.ts
+++ b/packages/react-docs/src/utils/typedoc_utils.ts
@@ -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 };
});
}
diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts
index 7c76f3e52..a29367485 100644
--- a/packages/sol-compiler/src/compiler.ts
+++ b/packages/sol-compiler/src/compiler.ts
@@ -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));
});
}
}
diff --git a/packages/sol-compiler/src/index.ts b/packages/sol-compiler/src/index.ts
index f8c2b577a..829e515ff 100644
--- a/packages/sol-compiler/src/index.ts
+++ b/packages/sol-compiler/src/index.ts
@@ -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';
diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts
index c918ed1f3..c153beb0f 100644
--- a/packages/sol-compiler/src/utils/compiler.ts
+++ b/packages/sol-compiler/src/utils/compiler.ts
@@ -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);
}
}
diff --git a/packages/sol-doc/CHANGELOG.json b/packages/sol-doc/CHANGELOG.json
new file mode 100644
index 000000000..c5bd78356
--- /dev/null
+++ b/packages/sol-doc/CHANGELOG.json
@@ -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
+ }
+ ]
+ }
+]
diff --git a/packages/sol-doc/bin/sol-doc.js b/packages/sol-doc/bin/sol-doc.js
new file mode 100755
index 000000000..35c9ae735
--- /dev/null
+++ b/packages/sol-doc/bin/sol-doc.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('../lib/src/cli.js');
diff --git a/packages/sol-doc/coverage/.gitkeep b/packages/sol-doc/coverage/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/sol-doc/coverage/.gitkeep
diff --git a/packages/sol-doc/package.json b/packages/sol-doc/package.json
new file mode 100644
index 000000000..618cb7ef7
--- /dev/null
+++ b/packages/sol-doc/package.json
@@ -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"
+ }
+}
diff --git a/packages/sol-doc/src/cli.ts b/packages/sol-doc/src/cli.ts
new file mode 100644
index 000000000..eb0f00bf6
--- /dev/null
+++ b/packages/sol-doc/src/cli.ts
@@ -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);
+});
diff --git a/packages/sol-doc/src/index.ts b/packages/sol-doc/src/index.ts
new file mode 100644
index 000000000..03f3c9de6
--- /dev/null
+++ b/packages/sol-doc/src/index.ts
@@ -0,0 +1 @@
+export { generateSolDocAsync } from './solidity_doc_generator';
diff --git a/packages/sol-doc/src/solidity_doc_generator.ts b/packages/sol-doc/src/solidity_doc_generator.ts
new file mode 100644
index 000000000..5ddf001a6
--- /dev/null
+++ b/packages/sol-doc/src/solidity_doc_generator.ts
@@ -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;
+}
diff --git a/packages/sol-doc/test/fixtures/contracts/MultipleReturnValues.sol b/packages/sol-doc/test/fixtures/contracts/MultipleReturnValues.sol
new file mode 100644
index 000000000..1e898622c
--- /dev/null
+++ b/packages/sol-doc/test/fixtures/contracts/MultipleReturnValues.sol
@@ -0,0 +1,7 @@
+pragma solidity ^0.4.24;
+
+contract MultipleReturnValues {
+ function methodWithMultipleReturnValues() public pure returns(int, int) {
+ return (0, 0);
+ }
+}
diff --git a/packages/sol-doc/test/fixtures/contracts/NatspecEverything.sol b/packages/sol-doc/test/fixtures/contracts/NatspecEverything.sol
new file mode 100644
index 000000000..c6ad3db81
--- /dev/null
+++ b/packages/sol-doc/test/fixtures/contracts/NatspecEverything.sol
@@ -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 {}
+}
diff --git a/packages/sol-doc/test/fixtures/contracts/TokenTransferProxy.sol b/packages/sol-doc/test/fixtures/contracts/TokenTransferProxy.sol
new file mode 100644
index 000000000..44570d459
--- /dev/null
+++ b/packages/sol-doc/test/fixtures/contracts/TokenTransferProxy.sol
@@ -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;
+ }
+}
diff --git a/packages/sol-doc/test/fixtures/contracts/TokenTransferProxyNoDevdoc.sol b/packages/sol-doc/test/fixtures/contracts/TokenTransferProxyNoDevdoc.sol
new file mode 100644
index 000000000..cc45a79e9
--- /dev/null
+++ b/packages/sol-doc/test/fixtures/contracts/TokenTransferProxyNoDevdoc.sol
@@ -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;
+ }
+}
diff --git a/packages/sol-doc/test/solidity_doc_generator_test.ts b/packages/sol-doc/test/solidity_doc_generator_test.ts
new file mode 100644
index 000000000..c780d3d31
--- /dev/null
+++ b/packages/sol-doc/test/solidity_doc_generator_test.ts
@@ -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();
+}
diff --git a/packages/sol-doc/test/util/chai_setup.ts b/packages/sol-doc/test/util/chai_setup.ts
new file mode 100644
index 000000000..1a8733093
--- /dev/null
+++ b/packages/sol-doc/test/util/chai_setup.ts
@@ -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);
+ },
+};
diff --git a/packages/sol-doc/tsconfig.json b/packages/sol-doc/tsconfig.json
new file mode 100644
index 000000000..2ee711adc
--- /dev/null
+++ b/packages/sol-doc/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig",
+ "compilerOptions": {
+ "outDir": "lib",
+ "rootDir": "."
+ },
+ "include": ["./src/**/*", "./test/**/*"]
+}
diff --git a/packages/sol-doc/tslint.json b/packages/sol-doc/tslint.json
new file mode 100644
index 000000000..ffaefe83a
--- /dev/null
+++ b/packages/sol-doc/tslint.json
@@ -0,0 +1,3 @@
+{
+ "extends": ["@0xproject/tslint-config"]
+}
diff --git a/packages/sra-spec/package.json b/packages/sra-spec/package.json
index f16711ea0..d4e89db53 100644
--- a/packages/sra-spec/package.json
+++ b/packages/sra-spec/package.json
@@ -9,7 +9,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"serve": "redoc-cli serve lib/api.json --watch",
- "watch_without_deps": "run-p build-json:watch serve",
+ "watch_without_deps": "run-p build:watch serve",
"lint": "tslint --project .",
"test": "swagger-cli validate lib/api.json",
"rebuild_and_test": "run-s clean build test",
@@ -19,7 +19,7 @@
"clean": "shx rm -rf lib",
"build": "tsc -b && yarn copy_md_files && yarn build-json",
"build-json": "node ./lib/build_scripts/buildJson",
- "build-json:watch": "chokidar 'src/**/*' -c 'yarn build-json' ",
+ "build:watch": "chokidar 'src/**/*' -c 'yarn build' ",
"copy_md_files": "copyfiles -u 2 './src/md/**/*.md' ./lib/src/md",
"deploy-site": "discharge deploy"
},
diff --git a/packages/sra-spec/src/api.ts b/packages/sra-spec/src/api.ts
index f80d343d8..7cecb0369 100644
--- a/packages/sra-spec/src/api.ts
+++ b/packages/sra-spec/src/api.ts
@@ -249,7 +249,7 @@ export const api: OpenApiSpec = {
},
},
'/v2/order_config': {
- get: {
+ post: {
description: `Relayers have full discretion over the orders that they are willing to host on their orderbooks (e.g what fees they charge, etc...). In order for traders to discover their requirements programmatically, they can send an incomplete order to this endpoint and receive the missing fields, specifc to that order. This gives relayers a large amount of flexibility to tailor fees to unique traders, trading pairs and volume amounts. Submit a partial order and receive information required to complete the order: \`senderAddress\`, \`feeRecipientAddress\`, \`makerFee\`, \`takerFee\`. `,
operationId: 'getOrderConfig',
parameters: generateParameters([], false),
diff --git a/packages/sra-spec/src/examples/relayerApiAssetDataPairsResponse.ts b/packages/sra-spec/src/examples/relayerApiAssetDataPairsResponse.ts
index 9eead5239..3ab7b29c0 100644
--- a/packages/sra-spec/src/examples/relayerApiAssetDataPairsResponse.ts
+++ b/packages/sra-spec/src/examples/relayerApiAssetDataPairsResponse.ts
@@ -8,13 +8,14 @@ export const relayerApiAssetDataPairsResponse = {
minAmount: '0',
maxAmount: '10000000000000000000',
precision: 5,
- assetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
+ assetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
},
assetDataB: {
minAmount: '0',
- maxAmount: '50000000000000000000',
+ maxAmount: '1',
precision: 5,
- assetData: '0x0257179264389b814a946f3e92105513705ca6b990',
+ assetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
},
},
],
diff --git a/packages/sra-spec/src/examples/relayerApiOrder.ts b/packages/sra-spec/src/examples/relayerApiOrder.ts
index 31181d677..e3ae66dc3 100644
--- a/packages/sra-spec/src/examples/relayerApiOrder.ts
+++ b/packages/sra-spec/src/examples/relayerApiOrder.ts
@@ -5,13 +5,14 @@ export const relayerApiOrder = {
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerAssetAmount: '10000000000000000',
- takerAssetAmount: '20000000000000000',
+ takerAssetAmount: '1',
makerFee: '100000000000000',
takerFee: '200000000000000',
expirationTimeSeconds: '1532560590',
salt: '1532559225',
- makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
- takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
+ makerAssetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
+ takerAssetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
},
diff --git a/packages/sra-spec/src/examples/relayerApiOrderConfigPayload.ts b/packages/sra-spec/src/examples/relayerApiOrderConfigPayload.ts
index 5251d5b4d..cca68b84d 100644
--- a/packages/sra-spec/src/examples/relayerApiOrderConfigPayload.ts
+++ b/packages/sra-spec/src/examples/relayerApiOrderConfigPayload.ts
@@ -2,9 +2,10 @@ export const relayerApiOrderConfigPayload = {
makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerAssetAmount: '10000000000000000',
- takerAssetAmount: '20000000000000000',
- makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
- takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
+ takerAssetAmount: '1',
+ makerAssetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
+ takerAssetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationTimeSeconds: '1532560590',
};
diff --git a/packages/sra-spec/src/examples/relayerApiOrderbookResponse.ts b/packages/sra-spec/src/examples/relayerApiOrderbookResponse.ts
index 40c09eff9..7f0772649 100644
--- a/packages/sra-spec/src/examples/relayerApiOrderbookResponse.ts
+++ b/packages/sra-spec/src/examples/relayerApiOrderbookResponse.ts
@@ -11,13 +11,14 @@ export const relayerApiOrderbookResponse = {
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerAssetAmount: '10000000000000000',
- takerAssetAmount: '20000000000000000',
+ takerAssetAmount: '1',
makerFee: '100000000000000',
takerFee: '200000000000000',
expirationTimeSeconds: '1532560590',
salt: '1532559225',
- makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
- takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
+ makerAssetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
+ takerAssetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
},
@@ -37,13 +38,14 @@ export const relayerApiOrderbookResponse = {
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerAssetAmount: '20000000000000000',
- takerAssetAmount: '10000000000000000',
+ takerAssetAmount: '1',
makerFee: '200000000000000',
takerFee: '100000000000000',
expirationTimeSeconds: '1532560590',
salt: '1532559225',
- makerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
- takerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
+ makerAssetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
+ takerAssetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
signature: '0x013842a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b3518891',
},
diff --git a/packages/sra-spec/src/examples/relayerApiOrdersResponse.ts b/packages/sra-spec/src/examples/relayerApiOrdersResponse.ts
index ac16e7e34..eb66b8e81 100644
--- a/packages/sra-spec/src/examples/relayerApiOrdersResponse.ts
+++ b/packages/sra-spec/src/examples/relayerApiOrdersResponse.ts
@@ -10,13 +10,14 @@ export const relayerApiOrdersResponse = {
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerAssetAmount: '10000000000000000',
- takerAssetAmount: '20000000000000000',
+ takerAssetAmount: '1',
makerFee: '100000000000000',
takerFee: '200000000000000',
expirationTimeSeconds: '1532560590',
salt: '1532559225',
- makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
- takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
+ makerAssetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
+ takerAssetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
},
diff --git a/packages/sra-spec/src/examples/signedOrder.ts b/packages/sra-spec/src/examples/signedOrder.ts
index 440566027..8513c398f 100644
--- a/packages/sra-spec/src/examples/signedOrder.ts
+++ b/packages/sra-spec/src/examples/signedOrder.ts
@@ -9,8 +9,9 @@ export const signedOrder = {
takerFee: '200000000000000',
expirationTimeSeconds: '1532560590',
salt: '1532559225',
- makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
- takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
+ makerAssetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498',
+ takerAssetData:
+ '0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
};
diff --git a/packages/sra-spec/src/md/introduction.md b/packages/sra-spec/src/md/introduction.md
index 6f733c9ab..f27186f41 100644
--- a/packages/sra-spec/src/md/introduction.md
+++ b/packages/sra-spec/src/md/introduction.md
@@ -180,7 +180,7 @@ The identifier for the Proxy uses a similar scheme to [ABI function selectors](h
```js
// ERC20 Proxy ID 0xf47261b0
bytes4(keccak256('ERC20Token(address)'));
-// ERC721 Proxy ID 0x08e937fa
+// ERC721 Proxy ID 0x02571792
bytes4(keccak256('ERC721Token(address,uint256)'));
```
@@ -192,10 +192,10 @@ For example, encoding the ERC20 token contract (address: 0x1dc4c1cefef38a777b15a
0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48
```
-Encoding the ERC721 token contract (address: `0x371b13d97f4bf77d724e78c16b7dc74099f40e84`), token id (id: `99`, which hex encoded is `0x63`) and the ERC721 Transfer Proxy (id: 0x08e937fa) would be:
+Encoding the ERC721 token contract (address: `0x371b13d97f4bf77d724e78c16b7dc74099f40e84`), token id (id: `99`, which hex encoded is `0x63`) and the ERC721 Transfer Proxy (id: 0x02571792) would be:
```bash
-0x08e937fa000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063
+0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063
```
For more information see [the Asset Proxy](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#erc20proxy) section of the v2 spec and the [Ethereum ABI Spec](https://solidity.readthedocs.io/en/develop/abi-spec.html).
diff --git a/packages/testnet-faucets/src/ts/handler.ts b/packages/testnet-faucets/src/ts/handler.ts
index 82e9a9494..e73eb1744 100644
--- a/packages/testnet-faucets/src/ts/handler.ts
+++ b/packages/testnet-faucets/src/ts/handler.ts
@@ -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);
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 5223bf299..5ef8b54a4 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -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;
+}
diff --git a/packages/typescript-typings/types/solc/index.d.ts b/packages/typescript-typings/types/solc/index.d.ts
index 571bae101..f4c05cd7c 100644
--- a/packages/typescript-typings/types/solc/index.d.ts
+++ b/packages/typescript-typings/types/solc/index.d.ts
@@ -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;
}
diff --git a/packages/website/md/docs/connect/2.0.0/introduction.md b/packages/website/md/docs/connect/2.0.0/introduction.md
index de7ece7ae..8e251b327 100644
--- a/packages/website/md/docs/connect/2.0.0/introduction.md
+++ b/packages/website/md/docs/connect/2.0.0/introduction.md
@@ -1,3 +1 @@
-<b>**NOTE:** Release candidate versions are meant to work with V2 of the Standard Relayer API. To interact with V1, select a 1.X version of connect.</b>
-
Welcome to the [0x Connect](https://github.com/0xProject/0x-monorepo/tree/development/packages/connect) documentation! 0x Connect is a Javascript library that makes it easy to interact with relayers that conform to the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api). Functionality includes getting supported asset pairs from a relayer, getting orders filtered by different attributes, getting individual orders specified by order hash, getting orderbooks for specific asset pairs, getting fee information, and submitting orders.
diff --git a/packages/website/md/docs/contract_wrappers/introduction.md b/packages/website/md/docs/contract_wrappers/introduction.md
index 74254bdad..ccc81b373 100644
--- a/packages/website/md/docs/contract_wrappers/introduction.md
+++ b/packages/website/md/docs/contract_wrappers/introduction.md
@@ -1,3 +1 @@
-<b>**NOTE:** Release candidate versions are meant to work with V2 of 0x protocol. To interact with V1, select a 0.X version.</b>
-
Welcome to the [Contract-wrappers](https://github.com/0xProject/0x-monorepo/tree/development/packages/contract-wrappers) documentation! Contract-wrappers is a library for interacting with the Ethereum smart contracts that make up the 0x protocol. With it, you can easily send transactions and make calls to the 0x smart contracts as well as any token adhering to the token standards supported by the protocol (currently ERC20 & ERC721).
diff --git a/packages/website/md/docs/json_schemas/1.0.0/introduction.md b/packages/website/md/docs/json_schemas/1.0.0/introduction.md
index cc777b1a8..a27f4b521 100644
--- a/packages/website/md/docs/json_schemas/1.0.0/introduction.md
+++ b/packages/website/md/docs/json_schemas/1.0.0/introduction.md
@@ -1,5 +1,3 @@
-<b>**NOTE:** Release candidate versions are meant to work with V2 of 0x protocol. To interact with V1, select a 0.X version.</b>
-
Welcome to the [@0xproject/json-schemas](https://github.com/0xProject/0x-monorepo/tree/development/packages/json-schemas) documentation! This package provides JSON schemas for validating 0x Protocol & Standard Relayer API data structures. It provides both the raw JSON schemas and a schema validator class to interact with them from a JS project.
If you are not using a Javascript-based language for your project, you can copy-paste the JSON schemas within this package and use them together with a [JSON Schema](http://json-schema.org/) implementation in your [language of choice](http://json-schema.org/implementations.html) (e.g Python, Haskell, Go, C, C++, Rust, Ruby, Scala, etc...).
diff --git a/packages/website/md/docs/smart_contracts/1.0.0/introduction.md b/packages/website/md/docs/smart_contracts/1.0.0/introduction.md
index 566a573b6..79a8f00fd 100644
--- a/packages/website/md/docs/smart_contracts/1.0.0/introduction.md
+++ b/packages/website/md/docs/smart_contracts/1.0.0/introduction.md
@@ -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.
diff --git a/packages/website/md/docs/smart_contracts/2.0.0/introduction.md b/packages/website/md/docs/smart_contracts/2.0.0/introduction.md
new file mode 100644
index 000000000..4aa31db3d
--- /dev/null
+++ b/packages/website/md/docs/smart_contracts/2.0.0/introduction.md
@@ -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)
diff --git a/packages/website/public/images/coinbase_wallet_logo.png b/packages/website/public/images/coinbase_wallet_logo.png
new file mode 100644
index 000000000..04c1b7290
--- /dev/null
+++ b/packages/website/public/images/coinbase_wallet_logo.png
Binary files differ
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 632a63016..c420bbf3a 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -66,7 +66,7 @@ const providerToName: { [provider: string]: string } = {
[Providers.Metamask]: constants.PROVIDER_NAME_METAMASK,
[Providers.Parity]: constants.PROVIDER_NAME_PARITY_SIGNER,
[Providers.Mist]: constants.PROVIDER_NAME_MIST,
- [Providers.Toshi]: constants.PROVIDER_NAME_TOSHI,
+ [Providers.CoinbaseWallet]: constants.PROVIDER_NAME_COINBASE_WALLET,
[Providers.Cipher]: constants.PROVIDER_NAME_CIPHER,
};
diff --git a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
index d618c8318..1035d4ad9 100644
--- a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
+++ b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
@@ -12,7 +12,7 @@ export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWallet
const followupText = isOnMobile
? `Please revisit this site in your mobile dApp browser to continue!`
: `Please refresh the page once you've done this to continue!`;
- const downloadText = isOnMobile ? 'Get the Toshi Wallet' : 'Get the MetaMask extension';
+ const downloadText = isOnMobile ? 'Get Coinbase Wallet' : 'Get the MetaMask extension';
return (
<div className="flex items-center flex-column">
<Text>First, you need to connect to a wallet. This will be used across all 0x relayers and dApps.</Text>
@@ -21,7 +21,7 @@ export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWallet
height="50px"
width="50px"
borderRadius="22%"
- src={isOnMobile ? '/images/toshi_logo.jpg' : '/images/metamask_icon.png'}
+ src={isOnMobile ? '/images/coinbase_wallet_logo.png' : '/images/metamask_icon.png'}
/>
<Container marginLeft="10px">
<a href={downloadLink} target="_blank">
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index b8d7ceea9..b42954f60 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -545,7 +545,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
<Section
header={!isMobile && <TextHeader labelText="0x Relayers" />}
body={
- <Container className="flex flex-column items-center">
+ <Container className="flex flex-column">
{isMobile && (
<Container marginTop="20px" marginBottom="20px">
{this._renderStartOnboarding()}
diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx
index 4aea1bbbb..91dbeb27a 100644
--- a/packages/website/ts/components/relayer_index/relayer_index.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_index.tsx
@@ -56,7 +56,11 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde
</div>
);
} else {
- const numberOfColumns = this._numberOfColumnsForScreenWidth(this.props.screenWidth);
+ const numberOfRelayers = this.state.relayerInfos.length;
+ const numberOfColumns = Math.min(
+ numberOfRelayers,
+ this._numberOfColumnsForScreenWidth(this.props.screenWidth),
+ );
return (
<GridList
cellHeight={CELL_HEIGHT}
diff --git a/packages/website/ts/components/wallet/body_overlay.tsx b/packages/website/ts/components/wallet/body_overlay.tsx
index 26359d0d2..3795f0eaa 100644
--- a/packages/website/ts/components/wallet/body_overlay.tsx
+++ b/packages/website/ts/components/wallet/body_overlay.tsx
@@ -13,7 +13,7 @@ import { AccountState, ProviderType } from 'ts/types';
import { utils } from 'ts/utils/utils';
const METAMASK_IMG_SRC = '/images/metamask_icon.png';
-const TOSHI_IMG_SRC = '/images/toshi_logo.jpg';
+const COINBASE_WALLET_IMG_SRC = '/images/coinbase_wallet_logo.png';
export interface BodyOverlayProps {
dispatcher: Dispatcher;
@@ -116,8 +116,8 @@ const UseDifferentWallet = (props: UseDifferentWallet) => {
const GetWalletCallToAction = () => {
const [downloadLink, isOnMobile] = utils.getBestWalletDownloadLinkAndIsMobile();
- const imageUrl = isOnMobile ? TOSHI_IMG_SRC : METAMASK_IMG_SRC;
- const text = isOnMobile ? 'Get Toshi Wallet' : 'Get MetaMask Wallet';
+ const imageUrl = isOnMobile ? COINBASE_WALLET_IMG_SRC : METAMASK_IMG_SRC;
+ const text = isOnMobile ? 'Get Coinbase Wallet' : 'Get MetaMask Wallet';
return (
<a href={downloadLink} target="_blank" style={{ textDecoration: 'none' }}>
<Island
diff --git a/packages/website/ts/containers/smart_contracts_documentation.ts b/packages/website/ts/containers/smart_contracts_documentation.ts
index 4f4479c83..8d69afe71 100644
--- a/packages/website/ts/containers/smart_contracts_documentation.ts
+++ b/packages/website/ts/containers/smart_contracts_documentation.ts
@@ -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': {
diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx
index 75295349d..e097578bc 100644
--- a/packages/website/ts/pages/about/about.tsx
+++ b/packages/website/ts/pages/about/about.tsx
@@ -194,7 +194,7 @@ const teamRow6: ProfileInfo[] = [
const teamRow7: ProfileInfo[] = [
{
name: 'Clay Robbins',
- title: 'Business Development Lead',
+ title: 'Ecosystem Development Lead',
description: `Growth & Business Development. Previously product and partnerships at Square. Economics at Dartmouth College.`,
image: 'images/team/clay.png',
linkedIn: 'https://www.linkedin.com/in/robbinsclay/',
diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx
index 9c144b93f..6f029b6a2 100644
--- a/packages/website/ts/pages/documentation/doc_page.tsx
+++ b/packages/website/ts/pages/documentation/doc_page.tsx
@@ -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({
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index 3c6d3df4d..4ec45c46e 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -491,7 +491,7 @@ export enum Providers {
Parity = 'PARITY',
Metamask = 'METAMASK',
Mist = 'MIST',
- Toshi = 'TOSHI',
+ CoinbaseWallet = 'COINBASE_WALLET',
Cipher = 'CIPHER',
}
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index 23d419907..18a4d8100 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -31,7 +31,7 @@ export const constants = {
PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
PROVIDER_NAME_MIST: 'Mist',
PROVIDER_NAME_CIPHER: 'Cipher Browser',
- PROVIDER_NAME_TOSHI: 'Toshi',
+ PROVIDER_NAME_COINBASE_WALLET: 'Coinbase Wallet',
PROVIDER_NAME_GENERIC: 'Injected Web3',
PROVIDER_NAME_PUBLIC: '0x Public',
ROLLBAR_ACCESS_TOKEN: '32c39bfa4bb6440faedc1612a9c13d28',
@@ -76,8 +76,8 @@ export const constants = {
URL_GITHUB_WIKI: 'https://github.com/0xProject/wiki',
URL_METAMASK_CHROME_STORE: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
URL_METAMASK_FIREFOX_STORE: 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/',
- URL_TOSHI_IOS_APP_STORE: 'https://itunes.apple.com/us/app/toshi-ethereum-wallet/id1278383455?mt=8',
- URL_TOSHI_ANDROID_APP_STORE: 'https://play.google.com/store/apps/details?id=org.toshi&hl=en_US',
+ URL_COINBASE_WALLET_IOS_APP_STORE: 'https://itunes.apple.com/us/app/coinbase-wallet/id1278383455?mt=8',
+ URL_COINBASE_WALLET_ANDROID_APP_STORE: 'https://play.google.com/store/apps/details?id=org.toshi&hl=en',
URL_METAMASK_HOMEPAGE: 'https://metamask.io/',
URL_METAMASK_OPERA_STORE: 'https://addons.opera.com/en/extensions/details/metamask/',
URL_MIST_DOWNLOAD: 'https://github.com/ethereum/mist/releases',
diff --git a/packages/website/ts/utils/doc_utils.ts b/packages/website/ts/utils/doc_utils.ts
index e313648bd..0e1d9ea6e 100644
--- a/packages/website/ts/utils/doc_utils.ts
+++ b/packages/website/ts/utils/doc_utils.ts
@@ -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) {
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index b45e37aeb..d083e0ffc 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -323,7 +323,7 @@ export const utils = {
} else if ((provider as any).isMetaMask) {
parsedProviderName = Providers.Metamask;
} else if (!_.isUndefined(_.get(window, 'SOFA'))) {
- parsedProviderName = Providers.Toshi;
+ parsedProviderName = Providers.CoinbaseWallet;
} else if (!_.isUndefined(_.get(window, '__CIPHER__'))) {
parsedProviderName = Providers.Cipher;
}
@@ -453,14 +453,14 @@ export const utils = {
if (isOnMobile) {
switch (operatingSystem) {
case OperatingSystemType.Android:
- downloadLink = constants.URL_TOSHI_ANDROID_APP_STORE;
+ downloadLink = constants.URL_COINBASE_WALLET_ANDROID_APP_STORE;
break;
case OperatingSystemType.iOS:
- downloadLink = constants.URL_TOSHI_IOS_APP_STORE;
+ downloadLink = constants.URL_COINBASE_WALLET_IOS_APP_STORE;
break;
default:
- // Toshi is only supported on these mobile OSes - just default to iOS
- downloadLink = constants.URL_TOSHI_IOS_APP_STORE;
+ // Coinbase wallet is only supported on these mobile OSes - just default to iOS
+ downloadLink = constants.URL_COINBASE_WALLET_IOS_APP_STORE;
}
} else {
switch (browserType) {
diff --git a/yarn.lock b/yarn.lock
index 19dd0c86e..6967c0425 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6088,7 +6088,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep:
ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
ethereumjs-util "^5.2.0"
ethereumjs-vm "2.3.5"
- ethereumjs-wallet "0.6.0"
+ ethereumjs-wallet "~0.6.0"
fake-merkle-patricia-tree "~1.0.1"
heap "~0.2.6"
js-scrypt "^0.2.0"
@@ -7229,6 +7229,10 @@ invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+invert-kv@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+
ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@@ -8136,6 +8140,12 @@ lcid@^1.0.0:
dependencies:
invert-kv "^1.0.0"
+lcid@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+ dependencies:
+ invert-kv "^2.0.0"
+
lcov-parse@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3"
@@ -8794,6 +8804,12 @@ make-promises-safe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/make-promises-safe/-/make-promises-safe-1.1.0.tgz#b4d28c61ef8ad5502f38dbb3a0ee89627f76ad61"
+map-age-cleaner@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74"
+ dependencies:
+ p-defer "^1.0.0"
+
map-cache@^0.2.0, map-cache@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@@ -8903,6 +8919,14 @@ mem@^1.1.0:
dependencies:
mimic-fn "^1.0.0"
+mem@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf"
+ dependencies:
+ map-age-cleaner "^0.1.1"
+ mimic-fn "^1.0.0"
+ p-is-promise "^1.1.0"
+
memdown@^1.0.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215"
@@ -10048,6 +10072,14 @@ os-locale@^2.0.0:
lcid "^1.0.0"
mem "^1.1.0"
+os-locale@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620"
+ dependencies:
+ execa "^0.10.0"
+ lcid "^2.0.0"
+ mem "^4.0.0"
+
os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
@@ -10067,6 +10099,10 @@ p-cancelable@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0"
+p-defer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+
p-each-series@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71"
@@ -15400,6 +15436,23 @@ yargs@^12.0.1:
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^10.1.0"
+yargs@^12.0.2:
+ version "12.0.2"
+ resolved "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
+ dependencies:
+ cliui "^4.0.0"
+ decamelize "^2.0.0"
+ find-up "^3.0.0"
+ get-caller-file "^1.0.1"
+ os-locale "^3.0.0"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^2.0.0"
+ which-module "^2.0.0"
+ y18n "^3.2.1 || ^4.0.0"
+ yargs-parser "^10.1.0"
+
yargs@^3.7.2:
version "3.32.0"
resolved "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995"