Comparing version 2.0.0-beta1 to 2.0.0-beta2
@@ -16,2 +16,11 @@ import { Dictionary } from 'ts-essentials'; | ||
export declare type StateMutability = 'pure' | 'view' | 'nonpayable' | 'payable'; | ||
export interface FunctionDocumentation { | ||
author?: string; | ||
details?: string; | ||
notice?: string; | ||
params?: { | ||
[paramName: string]: string; | ||
}; | ||
return?: string; | ||
} | ||
export interface FunctionDeclaration { | ||
@@ -22,2 +31,3 @@ name: string; | ||
outputs: AbiOutputParameter[]; | ||
documentation?: FunctionDocumentation; | ||
} | ||
@@ -37,2 +47,7 @@ export interface FunctionWithoutOutputDeclaration extends FunctionDeclaration { | ||
events: Dictionary<EventDeclaration[]>; | ||
documentation?: { | ||
author?: string; | ||
details?: string; | ||
notice?: string; | ||
}; | ||
} | ||
@@ -82,8 +97,18 @@ export interface RawAbiParameter { | ||
} | ||
export declare function parse(abi: Array<RawAbiDefinition>, rawName: string): Contract; | ||
export interface DocumentationResult { | ||
author?: string; | ||
details?: string; | ||
notice?: string; | ||
methods?: { | ||
[methodName: string]: FunctionDocumentation; | ||
}; | ||
} | ||
export declare function parse(abi: RawAbiDefinition[], rawName: string, documentation?: DocumentationResult): Contract; | ||
export declare function parseEvent(abiPiece: RawEventAbiDefinition): EventDeclaration; | ||
export declare function getFunctionDocumentation(abiPiece: RawAbiDefinition, documentation?: DocumentationResult): FunctionDocumentation | undefined; | ||
export declare function extractAbi(rawJson: string): RawAbiDefinition[]; | ||
export declare function extractBytecode(rawContents: string): BytecodeWithLinkReferences | undefined; | ||
export declare function extractDocumentation(rawContents: string): DocumentationResult | undefined; | ||
export declare function ensure0xPrefix(hexString: string): string; | ||
export declare function isConstant(fn: FunctionDeclaration): boolean; | ||
export declare function isConstantFn(fn: FunctionDeclaration): boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isConstantFn = exports.isConstant = exports.ensure0xPrefix = exports.extractBytecode = exports.extractAbi = exports.parseEvent = exports.parse = void 0; | ||
exports.isConstantFn = exports.isConstant = exports.ensure0xPrefix = exports.extractDocumentation = exports.extractBytecode = exports.extractAbi = exports.getFunctionDocumentation = exports.parseEvent = exports.parse = void 0; | ||
const js_sha3_1 = require("js-sha3"); | ||
@@ -10,3 +10,3 @@ const lodash_1 = require("lodash"); | ||
const normalizeName_1 = require("./normalizeName"); | ||
function parse(abi, rawName) { | ||
function parse(abi, rawName, documentation) { | ||
const constructors = []; | ||
@@ -29,3 +29,3 @@ let fallback; | ||
if (abiPiece.type === 'function') { | ||
functions.push(parseFunctionDeclaration(abiPiece)); | ||
functions.push(parseFunctionDeclaration(abiPiece, documentation)); | ||
return; | ||
@@ -47,2 +47,3 @@ } | ||
events: lodash_1.groupBy(events, (e) => e.name), | ||
documentation: documentation ? lodash_1.omit(documentation, ['methods']) : undefined, | ||
}; | ||
@@ -92,2 +93,7 @@ } | ||
} | ||
function getFunctionDocumentation(abiPiece, documentation) { | ||
const docKey = `${abiPiece.name}(${abiPiece.inputs.map(({ type }) => type).join(',')})`; | ||
return documentation && documentation.methods && documentation.methods[docKey]; | ||
} | ||
exports.getFunctionDocumentation = getFunctionDocumentation; | ||
function parseConstructor(abiPiece) { | ||
@@ -111,3 +117,3 @@ debug_1.debug(`Parsing constructor declaration`); | ||
} | ||
function parseFunctionDeclaration(abiPiece) { | ||
function parseFunctionDeclaration(abiPiece, documentation) { | ||
debug_1.debug(`Parsing function declaration "${abiPiece.name}"`); | ||
@@ -119,2 +125,3 @@ return { | ||
stateMutability: findStateMutability(abiPiece), | ||
documentation: getFunctionDocumentation(abiPiece, documentation), | ||
}; | ||
@@ -200,2 +207,27 @@ } | ||
exports.extractBytecode = extractBytecode; | ||
function extractDocumentation(rawContents) { | ||
let json; | ||
try { | ||
json = JSON.parse(rawContents); | ||
} | ||
catch (_a) { | ||
return undefined; | ||
} | ||
if (!json || (!json.devdoc && !json.userdoc)) | ||
return undefined; | ||
const result = json.devdoc || {}; | ||
// Merge devdoc and userdoc objects | ||
if (json.userdoc) { | ||
result.notice = json.userdoc.notice; | ||
if (!json.userdoc.methods) | ||
return result; | ||
result.methods = result.methods || {}; | ||
Object.entries(json.userdoc.methods).forEach(([key, { notice }]) => { | ||
if (result.methods) | ||
result.methods[key] = { ...result.methods[key], notice }; | ||
}); | ||
} | ||
return result; | ||
} | ||
exports.extractDocumentation = extractDocumentation; | ||
function extractLinkReferences(_bytecode, linkReferencesObj) { | ||
@@ -202,0 +234,0 @@ const bytecode = ensure0xPrefix(_bytecode); |
@@ -29,7 +29,8 @@ "use strict"; | ||
]; | ||
const module = _(possiblePaths).compact().map(tryRequire).compact().first(); | ||
if (!module || !module.default) { | ||
throw new Error(`Couldnt find ${ctx.rawConfig.target}. Tried loading: ${lodash_1.compact(possiblePaths).join(', ')}.\nPerhaps you forgot to install typechain-target-${target}?`); | ||
const moduleInfo = _(possiblePaths).compact().map(tryRequire).compact().first(); | ||
if (!moduleInfo || !moduleInfo.module.default) { | ||
throw new Error(`Couldn't find ${ctx.rawConfig.target}. Tried loading: ${lodash_1.compact(possiblePaths).join(', ')}.\nPerhaps you forgot to install typechain-target-${target}?`); | ||
} | ||
return new module.default(ctx); | ||
debug_1.debug('Plugin found at', moduleInfo.path); | ||
return new moduleInfo.module.default(ctx); | ||
} | ||
@@ -47,8 +48,14 @@ beforeRun() { | ||
exports.TypeChain = TypeChain; | ||
function tryRequire(path) { | ||
function tryRequire(name) { | ||
try { | ||
return require(path); | ||
const module = { | ||
module: require(name), | ||
name, | ||
path: require.resolve(name), | ||
}; | ||
debug_1.debug('Load successfully: ', name); | ||
return module; | ||
} | ||
catch (e) { | ||
debug_1.debug(e); | ||
debug_1.debug("Couldn't load: ", name); | ||
} | ||
@@ -55,0 +62,0 @@ } |
@@ -11,3 +11,3 @@ { | ||
], | ||
"version": "2.0.0-beta1", | ||
"version": "2.0.0-beta2", | ||
"license": "MIT", | ||
@@ -14,0 +14,0 @@ "repository": "https://github.com/ethereum-ts/Typechain", |
@@ -43,9 +43,9 @@ <p align="center"> | ||
| Package | Version | Description | | ||
| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------- | | ||
| [`typechain`](/packages/core) | [![npm](https://img.shields.io/npm/v/typechain.svg)](https://www.npmjs.com/package/typechain) | Core package | | ||
| [`@typechain/ethers-v4`](/packages/@typechain/ethers-v4) | [![npm](https://img.shields.io/npm/v/@typechain/ethers-v4.svg)](https://www.npmjs.com/package/@typechain/ethers-v4) | Ethers ver 4 support | | ||
| [`@typechain/truffle-v4`](/packages/@typechain/truffle-v4) | [![npm](https://img.shields.io/npm/v/@typechain/truffle-v4.svg)](https://www.npmjs.com/package/@typechain/truffle-v4) | Truffle ver 4 support | | ||
| [`@typechain/web3-v1`](/packages/@typechain/web3-v1) | [![npm](https://img.shields.io/npm/v/@typechain/web3-v1.svg)](https://www.npmjs.com/package/@typechain/web3-v1) | Web3 ver 1 support | | ||
| [`@typechain/web3-v2`](/packages/@typechain/web3-v2) | [![npm](https://img.shields.io/npm/v/@typechain/web3-v2.svg)](https://www.npmjs.com/package/@typechain/web3-v2) | Web3 ver 2 support | | ||
| Package | Version | Description | Examples | | ||
| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------- | -------------------------------- | | ||
| [`typechain`](/packages/core) | [![npm](https://img.shields.io/npm/v/typechain.svg)](https://www.npmjs.com/package/typechain) | Core package | - | | ||
| [`@typechain/ethers-v4`](/packages/@typechain/ethers-v4) | [![npm](https://img.shields.io/npm/v/@typechain/ethers-v4.svg)](https://www.npmjs.com/package/@typechain/ethers-v4) | Ethers ver 4 support | [example](./examples/ethers-v4) | | ||
| [`@typechain/truffle-v4`](/packages/@typechain/truffle-v4) | [![npm](https://img.shields.io/npm/v/@typechain/truffle-v4.svg)](https://www.npmjs.com/package/@typechain/truffle-v4) | Truffle ver 4 support | [example](./examples/truffle-v4) | | ||
| [`@typechain/web3-v1`](/packages/@typechain/web3-v1) | [![npm](https://img.shields.io/npm/v/@typechain/web3-v1.svg)](https://www.npmjs.com/package/@typechain/web3-v1) | Web3 ver 1 support | [example](./examples/web3-v1) | | ||
| [`@typechain/web3-v2`](/packages/@typechain/web3-v2) | [![npm](https://img.shields.io/npm/v/@typechain/web3-v2.svg)](https://www.npmjs.com/package/@typechain/web3-v2) | Web3 ver 2 support | [example](./examples/web3-v2) | | ||
@@ -52,0 +52,0 @@ ## Usage |
import { keccak_256 } from 'js-sha3' | ||
import { groupBy } from 'lodash' | ||
import { groupBy, omit } from 'lodash' | ||
import { Dictionary } from 'ts-essentials' | ||
@@ -27,2 +27,12 @@ | ||
export interface FunctionDocumentation { | ||
author?: string | ||
details?: string | ||
notice?: string | ||
params?: { | ||
[paramName: string]: string | ||
} | ||
return?: string | ||
} | ||
export interface FunctionDeclaration { | ||
@@ -33,2 +43,3 @@ name: string | ||
outputs: AbiOutputParameter[] | ||
documentation?: FunctionDocumentation | ||
} | ||
@@ -52,2 +63,7 @@ | ||
events: Dictionary<EventDeclaration[]> | ||
documentation?: { | ||
author?: string | ||
details?: string | ||
notice?: string | ||
} | ||
} | ||
@@ -106,3 +122,14 @@ | ||
export function parse(abi: Array<RawAbiDefinition>, rawName: string): Contract { | ||
// This is the combined interface for devdocs and userdocs | ||
// See https://solidity.readthedocs.io/en/v0.5.12/natspec-format.html#documentation-output | ||
export interface DocumentationResult { | ||
author?: string | ||
details?: string | ||
notice?: string | ||
methods?: { | ||
[methodName: string]: FunctionDocumentation | ||
} | ||
} | ||
export function parse(abi: RawAbiDefinition[], rawName: string, documentation?: DocumentationResult): Contract { | ||
const constructors: FunctionWithoutOutputDeclaration[] = [] | ||
@@ -132,3 +159,3 @@ let fallback: FunctionWithoutInputDeclaration | undefined | ||
if (abiPiece.type === 'function') { | ||
functions.push(parseFunctionDeclaration(abiPiece)) | ||
functions.push(parseFunctionDeclaration(abiPiece, documentation)) | ||
return | ||
@@ -154,2 +181,3 @@ } | ||
events: groupBy(events, (e) => e.name), | ||
documentation: documentation ? omit(documentation, ['methods']) : undefined, | ||
} | ||
@@ -203,2 +231,10 @@ } | ||
export function getFunctionDocumentation( | ||
abiPiece: RawAbiDefinition, | ||
documentation?: DocumentationResult, | ||
): FunctionDocumentation | undefined { | ||
const docKey = `${abiPiece.name}(${abiPiece.inputs.map(({ type }) => type).join(',')})` | ||
return documentation && documentation.methods && documentation.methods[docKey] | ||
} | ||
function parseConstructor(abiPiece: RawAbiDefinition): FunctionWithoutOutputDeclaration { | ||
@@ -225,3 +261,6 @@ debug(`Parsing constructor declaration`) | ||
function parseFunctionDeclaration(abiPiece: RawAbiDefinition): FunctionDeclaration { | ||
function parseFunctionDeclaration( | ||
abiPiece: RawAbiDefinition, | ||
documentation?: DocumentationResult, | ||
): FunctionDeclaration { | ||
debug(`Parsing function declaration "${abiPiece.name}"`) | ||
@@ -233,2 +272,3 @@ return { | ||
stateMutability: findStateMutability(abiPiece), | ||
documentation: getFunctionDocumentation(abiPiece, documentation), | ||
} | ||
@@ -328,2 +368,26 @@ } | ||
export function extractDocumentation(rawContents: string): DocumentationResult | undefined { | ||
let json | ||
try { | ||
json = JSON.parse(rawContents) | ||
} catch { | ||
return undefined | ||
} | ||
if (!json || (!json.devdoc && !json.userdoc)) return undefined | ||
const result: DocumentationResult = json.devdoc || {} | ||
// Merge devdoc and userdoc objects | ||
if (json.userdoc) { | ||
result.notice = json.userdoc.notice | ||
if (!json.userdoc.methods) return result | ||
result.methods = result.methods || {} | ||
Object.entries<{ notice: string }>(json.userdoc.methods).forEach(([key, { notice }]) => { | ||
if (result.methods) result.methods[key] = { ...result.methods[key], notice } | ||
}) | ||
} | ||
return result | ||
} | ||
function extractLinkReferences(_bytecode: string, linkReferencesObj?: any): BytecodeWithLinkReferences { | ||
@@ -330,0 +394,0 @@ const bytecode = ensure0xPrefix(_bytecode) |
@@ -38,7 +38,7 @@ import { TsGeneratorPlugin, TFileDesc, TContext, TOutput } from 'ts-generator' | ||
const module = _(possiblePaths).compact().map(tryRequire).compact().first() | ||
const moduleInfo = _(possiblePaths).compact().map(tryRequire).compact().first() | ||
if (!module || !module.default) { | ||
if (!moduleInfo || !moduleInfo.module.default) { | ||
throw new Error( | ||
`Couldnt find ${ctx.rawConfig.target}. Tried loading: ${compact(possiblePaths).join( | ||
`Couldn't find ${ctx.rawConfig.target}. Tried loading: ${compact(possiblePaths).join( | ||
', ', | ||
@@ -49,3 +49,5 @@ )}.\nPerhaps you forgot to install typechain-target-${target}?`, | ||
return new module.default(ctx) | ||
debug('Plugin found at', moduleInfo.path) | ||
return new moduleInfo.module.default(ctx) | ||
} | ||
@@ -66,7 +68,13 @@ | ||
function tryRequire(path: string): any { | ||
function tryRequire(name: string): { module: any; name: string; path: string } | undefined { | ||
try { | ||
return require(path) | ||
const module = { | ||
module: require(name), | ||
name, | ||
path: require.resolve(name), | ||
} | ||
debug('Load successfully: ', name) | ||
return module | ||
} catch (e) { | ||
debug(e) | ||
debug("Couldn't load: ", name) | ||
} | ||
@@ -73,0 +81,0 @@ } |
@@ -10,2 +10,3 @@ import { expect } from 'chai' | ||
extractBytecode, | ||
extractDocumentation, | ||
FunctionDeclaration, | ||
@@ -91,2 +92,66 @@ isConstant, | ||
describe('extractDocumentation', () => { | ||
const devUserDoc = `{ | ||
"devdoc": { | ||
"author" : "Larry A. Gardner", | ||
"details" : "All function calls are currently implemented without side effects", | ||
"methods" : | ||
{ | ||
"age(uint256)" : | ||
{ | ||
"author" : "Mary A. Botanist", | ||
"details" : "The Alexandr N. Tetearing algorithm could increase precision", | ||
"params" : | ||
{ | ||
"rings" : "The number of rings from dendrochronological sample" | ||
}, | ||
"return" : "age in years, rounded up for partial years" | ||
} | ||
}, | ||
"title" : "A simulator for trees" | ||
}, | ||
"userdoc": { | ||
"methods" : | ||
{ | ||
"age(uint256)" : | ||
{ | ||
"notice" : "Calculate tree age in years, rounded up, for live trees" | ||
} | ||
}, | ||
"notice" : "You can use this contract for only the most basic simulation" | ||
} | ||
}` | ||
const userDoc = `{ | ||
"userdoc": { | ||
"methods" : | ||
{ | ||
"age(uint256)" : | ||
{ | ||
"notice" : "Calculate tree age in years, rounded up, for live trees" | ||
} | ||
}, | ||
"notice" : "You can use this contract for only the most basic simulation" | ||
} | ||
}` | ||
it('should merge devdoc and userdoc', () => { | ||
const doc = extractDocumentation(devUserDoc) | ||
if (!doc) throw new Error('Doc should exist') | ||
expect(doc.notice).to.equal('You can use this contract for only the most basic simulation') | ||
expect(doc.author).to.equal('Larry A. Gardner') | ||
if (!doc.methods) throw new Error('Methods should exist') | ||
expect(doc.methods['age(uint256)'].author).to.equal('Mary A. Botanist') | ||
expect(doc.methods['age(uint256)'].notice).to.equal('Calculate tree age in years, rounded up, for live trees') | ||
}) | ||
it('should parse userdoc only', () => { | ||
const doc = extractDocumentation(userDoc) | ||
if (!doc) throw new Error('Doc should exist') | ||
expect(doc.notice).to.equal('You can use this contract for only the most basic simulation') | ||
if (!doc.methods) throw new Error('Methods should exist') | ||
expect(doc.methods['age(uint256)'].notice).to.equal('Calculate tree age in years, rounded up, for live trees') | ||
}) | ||
}) | ||
describe('extractBytecode with link references', () => { | ||
@@ -215,2 +280,41 @@ // tslint:disable:max-line-length | ||
describe('parse', () => { | ||
describe('functions', () => { | ||
const abiPiece = { | ||
constant: false, | ||
inputs: [ | ||
{ | ||
name: 'foo', | ||
type: 'uint256', | ||
}, | ||
{ | ||
name: 'bar', | ||
type: 'bytes32', | ||
}, | ||
], | ||
name: 'doFooBar', | ||
outputs: [], | ||
payable: false, | ||
type: 'function', | ||
} | ||
const documentation = { | ||
details: 'A cool contract that does cool stuff', | ||
methods: { | ||
'doFooBar(uint256,bytes32)': { | ||
details: 'Does a bit of foo and some bar', | ||
params: { | ||
foo: 'A bit of foo', | ||
bar: 'Some bar', | ||
}, | ||
}, | ||
}, | ||
} | ||
it('should get the documentation', () => { | ||
const res = parse([abiPiece], 'ACoolContract', documentation) | ||
expect(res.functions.doFooBar[0].documentation).to.deep.equal(documentation.methods['doFooBar(uint256,bytes32)']) | ||
expect(res.documentation!.details).to.equal(documentation.details) | ||
}) | ||
}) | ||
describe('fallback functions', () => { | ||
@@ -266,2 +370,3 @@ it('should work on output-less fallback functions', () => { | ||
fallback: undefined, | ||
documentation: undefined, | ||
functions: {}, | ||
@@ -268,0 +373,0 @@ name: 'Sc1', |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
181542
1900
0
4