diff options
Diffstat (limited to 'packages/abi-gen')
-rw-r--r-- | packages/abi-gen/CHANGELOG.md | 7 | ||||
-rw-r--r-- | packages/abi-gen/README.md | 21 | ||||
-rw-r--r-- | packages/abi-gen/package.json | 92 | ||||
-rw-r--r-- | packages/abi-gen/scripts/postpublish.js | 15 | ||||
-rw-r--r-- | packages/abi-gen/src/index.ts | 28 | ||||
-rw-r--r-- | packages/abi-gen/src/types.ts | 8 | ||||
-rw-r--r-- | packages/abi-gen/src/utils.ts | 37 | ||||
-rw-r--r-- | packages/abi-gen/tsconfig.json | 20 | ||||
-rw-r--r-- | packages/abi-gen/tslint.json | 4 |
9 files changed, 145 insertions, 87 deletions
diff --git a/packages/abi-gen/CHANGELOG.md b/packages/abi-gen/CHANGELOG.md new file mode 100644 index 000000000..fb2c6eb24 --- /dev/null +++ b/packages/abi-gen/CHANGELOG.md @@ -0,0 +1,7 @@ +# CHANGELOG + +## v0.1.0 - _January 11, 2018_ + +* Fixed array typings with union types (#295) +* Add event ABIs to context data passed to templates (#302) +* Add constructor ABIs to context data passed to templates (#304) diff --git a/packages/abi-gen/README.md b/packages/abi-gen/README.md index 16dd9b969..1188bd437 100644 --- a/packages/abi-gen/README.md +++ b/packages/abi-gen/README.md @@ -5,11 +5,14 @@ It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/w You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions. For an example of the generated [wrapper files](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js. -[Here](https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates) are the templates used to generate those files. +[Here](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files. + +## Installation -## Instalation `yarn add -g @0xproject/abi-gen` + ## Usage + ``` abi-gen Options: @@ -19,8 +22,10 @@ Options: --templates Folder where to search for templates [string] [required] --output Folder where to put the output files [string] [required] ``` + ## ABI files -You're required to pass a [glob](https://en.wikipedia.org/wiki/Glob_(programming)) template where your abi files are located. + +You're required to pass a [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) template where your abi files are located. TL;DR - here is the example from 0x.js. `--abiGlob 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry).json` @@ -28,12 +33,18 @@ TL;DR - here is the example from 0x.js. We could've just used `--abiGlob 'src/artifacts/*.json` but we wanted to exclude some of the abi files. The abi file should be either a [Truffle](http://truffleframework.com/) contract artifact (a JSON object with an abi key) or a JSON abi array. + ## How to write custom templates? -The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates) and start adjusting them for your needs. -We use [handlebars](handlebarsjs.com) template engine under the hood. + +The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs. +We use [handlebars](http://handlebarsjs.com/) template engine under the hood. You need to have a master template called `contract.mustache`. it will be used to generate each contract wrapper. Although - you don't need and probably shouldn't write all your logic in a single template file. You can write [partial templates](http://handlebarsjs.com/partials.html) and as long as they are within a partials folder - they will be registered and available. + ## Which data/context do I get in my templates? + For now you don't get much on top of methods abi, some useful helpers and a contract name because it was enough for our use-case, but if you need something else - create a PR. See the [type definition](https://github.com/0xProject/0x.js/tree/development/packages/abi-gen/src/types.ts) of what we pass to the render method. + ## Output files + Output files will be generated within an output folder with names converted to camel case and taken from abi file names. If you already have some files in that folder they will be overwritten. diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 9ce64f818..8d2dee18a 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -1,48 +1,48 @@ { - "name": "abi-gen", - "version": "0.0.1", - "description": "Generate contract wrappers from ABI and handlebars templates", - "main": "lib/index.js", - "types": "lib/index.d.ts", - "scripts": { - "lint": "tslint --project . 'src/**/*.ts'", - "clean": "shx rm -rf lib", - "build": "tsc" - }, - "bin": { - "abi-gen": "lib/index.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x.js.git" - }, - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/0xProject/0x.js/issues" - }, - "homepage": "https://github.com/0xProject/0x.js/packages/abi-gen/README.md", - "dependencies": { - "bignumber.js": "~4.1.0", - "chalk": "^2.3.0", - "glob": "^7.1.2", - "handlebars": "^4.0.11", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "to-snake-case": "^1.0.0", - "web3": "^0.20.0", - "yargs": "^10.0.3" - }, - "devDependencies": { - "@0xproject/tslint-config": "^0.2.0", - "@types/glob": "^5.0.33", - "@types/handlebars": "^4.0.36", - "@types/mkdirp": "^0.5.1", - "@types/node": "^8.0.53", - "@types/yargs": "^8.0.2", - "npm-run-all": "^4.1.2", - "shx": "^0.2.2", - "tslint": "5.8.0", - "typescript": "~2.6.1", - "web3-typescript-typings": "^0.7.2" - } + "name": "@0xproject/abi-gen", + "version": "0.1.3", + "description": "Generate contract wrappers from ABI and handlebars templates", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "lint": "tslint --project . 'src/**/*.ts'", + "clean": "shx rm -rf lib", + "build": "tsc" + }, + "bin": { + "abi-gen": "lib/index.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x.js.git" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/0xProject/0x.js/issues" + }, + "homepage": "https://github.com/0xProject/0x.js/packages/abi-gen/README.md", + "dependencies": { + "@0xproject/utils": "^0.2.1", + "chalk": "^2.3.0", + "glob": "^7.1.2", + "handlebars": "^4.0.11", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "to-snake-case": "^1.0.0", + "web3": "^0.20.0", + "yargs": "^10.0.3" + }, + "devDependencies": { + "@0xproject/tslint-config": "^0.4.3", + "@types/glob": "^5.0.33", + "@types/handlebars": "^4.0.36", + "@types/mkdirp": "^0.5.1", + "@types/node": "^8.0.53", + "@types/yargs": "^10.0.0", + "npm-run-all": "^4.1.2", + "shx": "^0.2.2", + "tslint": "5.8.0", + "typescript": "~2.6.1", + "web3-typescript-typings": "^0.9.5" + } } diff --git a/packages/abi-gen/scripts/postpublish.js b/packages/abi-gen/scripts/postpublish.js new file mode 100644 index 000000000..16d67e03f --- /dev/null +++ b/packages/abi-gen/scripts/postpublish.js @@ -0,0 +1,15 @@ +const postpublish_utils = require('../../../scripts/postpublish_utils'); +const packageJSON = require('../package.json'); + +const subPackageName = packageJSON.name; + +postpublish_utils + .getLatestTagAndVersionAsync(subPackageName) + .then(function(result) { + const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version); + const assets = []; + return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets); + }) + .catch(function(err) { + throw err; + }); diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts index 19d289e49..527af32b1 100644 --- a/packages/abi-gen/src/index.ts +++ b/packages/abi-gen/src/index.ts @@ -2,7 +2,7 @@ import chalk from 'chalk'; import * as fs from 'fs'; -import {sync as globSync} from 'glob'; +import { sync as globSync } from 'glob'; import * as Handlebars from 'handlebars'; import * as _ from 'lodash'; import * as mkdirp from 'mkdirp'; @@ -11,10 +11,12 @@ import * as yargs from 'yargs'; import toSnakeCase = require('to-snake-case'); import * as Web3 from 'web3'; -import {ContextData, ParamKind} from './types'; -import {utils} from './utils'; +import { ContextData, ParamKind } from './types'; +import { utils } from './utils'; +const ABI_TYPE_CONSTRUCTOR = 'constructor'; const ABI_TYPE_METHOD = 'function'; +const ABI_TYPE_EVENT = 'event'; const MAIN_TEMPLATE_NAME = 'contract.mustache'; const args = yargs @@ -32,8 +34,7 @@ const args = yargs describe: 'Folder where to put the output files', type: 'string', demand: true, - }) - .argv; + }).argv; function writeOutputFile(name: string, renderedTsCode: string): void { const fileName = toSnakeCase(name); @@ -66,14 +67,20 @@ for (const abiFileName of abiFileNames) { const namedContent = utils.getNamedContent(abiFileName); utils.log(`Processing: ${chalk.bold(namedContent.name)}...`); const parsedContent = JSON.parse(namedContent.content); - const ABI = _.isArray(parsedContent) ? - parsedContent : // ABI file - parsedContent.abi; // Truffle contracts file + const ABI = _.isArray(parsedContent) + ? parsedContent // ABI file + : parsedContent.abi; // Truffle contracts file if (_.isUndefined(ABI)) { utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`); utils.log(`Please make sure your ABI file is either an array with ABI entries or an object with the abi key`); process.exit(1); } + + let ctor = ABI.find((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_CONSTRUCTOR) as Web3.ConstructorAbi; + if (_.isUndefined(ctor)) { + ctor = utils.getEmptyConstructor(); // The constructor exists, but it's implicit in JSON's ABI definition + } + const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[]; const methodsData = _.map(methodAbis, methodAbi => { _.map(methodAbi.inputs, input => { @@ -89,9 +96,14 @@ for (const abiFileName of abiFileNames) { }; return methodData; }); + + const eventAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_EVENT) as Web3.EventAbi[]; + const contextData = { contractName: namedContent.name, + ctor, methods: methodsData, + events: eventAbis, }; const renderedTsCode = template(contextData); writeOutputFile(namedContent.name, renderedTsCode); diff --git a/packages/abi-gen/src/types.ts b/packages/abi-gen/src/types.ts index 1dc039c83..e82ab824b 100644 --- a/packages/abi-gen/src/types.ts +++ b/packages/abi-gen/src/types.ts @@ -5,6 +5,13 @@ export enum ParamKind { Output = 'output', } +export enum AbiType { + Function = 'function', + Constructor = 'constructor', + Event = 'event', + Fallback = 'fallback', +} + export interface Method extends Web3.MethodAbi { singleReturnValue: boolean; } @@ -12,4 +19,5 @@ export interface Method extends Web3.MethodAbi { export interface ContextData { contractName: string; methods: Method[]; + events: Web3.EventAbi[]; } diff --git a/packages/abi-gen/src/utils.ts b/packages/abi-gen/src/utils.ts index eaf5a30cc..14255643a 100644 --- a/packages/abi-gen/src/utils.ts +++ b/packages/abi-gen/src/utils.ts @@ -1,8 +1,9 @@ import * as fs from 'fs'; import * as _ from 'lodash'; import * as path from 'path'; +import * as Web3 from 'web3'; -import {ParamKind} from './types'; +import { AbiType, ParamKind } from './types'; export const utils = { solTypeToTsType(paramKind: ParamKind, solType: string): string { @@ -10,23 +11,28 @@ export const utils = { if (solType.match(trailingArrayRegex)) { const arrayItemSolType = solType.replace(trailingArrayRegex, ''); const arrayItemTsType = utils.solTypeToTsType(paramKind, arrayItemSolType); - const arrayTsType = `${arrayItemTsType}[]`; + const arrayTsType = utils.isUnionType(arrayItemTsType) + ? `Array<${arrayItemTsType}>` + : `${arrayItemTsType}[]`; return arrayTsType; } else { const solTypeRegexToTsType = [ - {regex: '^string$', tsType: 'string'}, - {regex: '^address$', tsType: 'string'}, - {regex: '^bool$', tsType: 'boolean'}, - {regex: '^u?int\\d*$', tsType: 'BigNumber'}, - {regex: '^bytes\\d*$', tsType: 'string'}, + { regex: '^string$', tsType: 'string' }, + { regex: '^address$', tsType: 'string' }, + { regex: '^bool$', tsType: 'boolean' }, + { regex: '^u?int\\d*$', tsType: 'BigNumber' }, + { regex: '^bytes\\d*$', tsType: 'string' }, ]; if (paramKind === ParamKind.Input) { // web3 allows to pass those an non-bignumbers and that's nice // but it always returns stuff as BigNumbers - solTypeRegexToTsType.unshift({regex: '^u?int(8|16|32)?$', tsType: 'number|BigNumber'}); + solTypeRegexToTsType.unshift({ + regex: '^u?int(8|16|32)?$', + tsType: 'number|BigNumber', + }); } for (const regexAndTxType of solTypeRegexToTsType) { - const {regex, tsType} = regexAndTxType; + const { regex, tsType } = regexAndTxType; if (solType.match(regex)) { return tsType; } @@ -34,6 +40,9 @@ export const utils = { throw new Error(`Unknown Solidity type found: ${solType}`); } }, + isUnionType(tsType: string): boolean { + return tsType === 'number|BigNumber'; + }, log(...args: any[]): void { console.log(...args); // tslint:disable-line:no-console }, @@ -41,7 +50,7 @@ export const utils = { const name = path.parse(filename).name; return name; }, - getNamedContent(filename: string): {name: string; content: string} { + getNamedContent(filename: string): { name: string; content: string } { const name = utils.getPartialNameFromFileName(filename); try { const content = fs.readFileSync(filename).toString(); @@ -53,4 +62,12 @@ export const utils = { throw new Error(`Failed to read ${filename}: ${err}`); } }, + getEmptyConstructor(): Web3.ConstructorAbi { + return { + type: AbiType.Constructor, + stateMutability: 'nonpayable', + payable: false, + inputs: [], + }; + }, }; diff --git a/packages/abi-gen/tsconfig.json b/packages/abi-gen/tsconfig.json index 695f2a47e..5e0c7c6d3 100644 --- a/packages/abi-gen/tsconfig.json +++ b/packages/abi-gen/tsconfig.json @@ -1,17 +1,7 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "lib": ["es2015", "dom"], - "outDir": "lib", - "sourceMap": true, - "declaration": true, - "noImplicitAny": true, - "strictNullChecks": true - }, - "include": [ - "./src/**/*", - "./test/**/*", - "../../node_modules/web3-typescript-typings/index.d.ts" - ] + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*", "../../node_modules/web3-typescript-typings/index.d.ts"] } diff --git a/packages/abi-gen/tslint.json b/packages/abi-gen/tslint.json index a07795151..ffaefe83a 100644 --- a/packages/abi-gen/tslint.json +++ b/packages/abi-gen/tslint.json @@ -1,5 +1,3 @@ { - "extends": [ - "@0xproject/tslint-config" - ] + "extends": ["@0xproject/tslint-config"] } |