Skip to content

Commit

Permalink
Merge pull request #196 from pash7ka/bignumber-to-bn
Browse files Browse the repository at this point in the history
Add truffle v5 target, switch from BigNumber to BN
  • Loading branch information
krzkaczor committed Dec 27, 2019
2 parents 39cba20 + 4800418 commit f406c18
Show file tree
Hide file tree
Showing 6 changed files with 280 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -5,7 +5,7 @@
"license": "MIT",
"scripts": {
"prepare": "patch-package",
"build": "rm -rf ./dist && tsc -p ./tsconfig.prod.json && (cd packages/core/ && yarn build) && (cd packages/typechain-target-ethers/ && yarn build) && (cd packages/typechain-target-truffle/ && yarn build) && (cd packages/typechain-target-web3-v1/ && yarn build) && (cd packages/typechain-target-web3-v2/ && yarn build)",
"build": "rm -rf ./dist && tsc -p ./tsconfig.prod.json && (cd packages/core/ && yarn build) && (cd packages/typechain-target-ethers/ && yarn build) && (cd packages/typechain-target-truffle/ && yarn build) && (cd packages/typechain-target-truffle-v5/ && yarn build) && (cd packages/typechain-target-web3-v1/ && yarn build) && (cd packages/typechain-target-web3-v2/ && yarn build)",
"tslint": "tslint -p ./tsconfig.json -e 'node_modules/**/*' -e '**/node_modules/**/*' 'packages/**/*.ts'",
"tslint:fix": "tslint --fix --format stylish -p ./tsconfig.json -e 'node_modules/**/*' -e '**/node_modules/**/*' 'packages/**/*.ts'",
"format": "prettier --list-different 'packages/**/*.{ts,tsx,json,md,gql}' README.md 'test/integration/**/*.{ts,tsx,json,md,gql}'",
Expand Down
21 changes: 21 additions & 0 deletions packages/typechain-target-truffle-v5/README.md
@@ -0,0 +1,21 @@
# Typechain target Truffle

<p align="center">
<img src="https://github.com/Neufund/TypeChain/blob/d82f3cc644a11e22ca8e42505c16f035e2f2555d/docs/images/typechain-logo.png?raw=true" width="300" alt="TypeChain">
<h3 align="center">TypeChain target Truffle v5</h3>
<p align="center">馃攲 TypeScript bindings for Truffle v5 smartcontracts</p>

<p align="center">
<a href="https://circleci.com/gh/ethereum-ts/TypeChain"><img alt="Build Status" src="https://circleci.com/gh/ethereum-ts/TypeChain/tree/master.svg?style=svg"></a>
<a href="https://coveralls.io/github/ethereum-ts/TypeChain?branch=master"><img alt="Coverage" src="https://coveralls.io/repos/github/ethereum-ts/TypeChain/badge.svg?branch=master"></a>
<img alt="Downloads" src="https://img.shields.io/npm/dm/typechain.svg">
<a href="https://github.com/prettier/prettier"><img alt="Prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg"></a>
<a href="/package.json"><img alt="Software License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square"></a>
</p>

<p align="center">
<a href="https://blog.neufund.org/introducing-typechain-typescript-bindings-for-ethereum-smart-contracts-839fc2becf22">Medium post</a> | <a href="https://www.youtube.com/watch?v=9x6AkShGkwU">DappCon Video</a>
</p>
</p>

## [TypeChain readme](https://github.com/ethereum-ts/TypeChain)
175 changes: 175 additions & 0 deletions packages/typechain-target-truffle-v5/lib/generation.ts
@@ -0,0 +1,175 @@
import {
Contract,
AbiParameter,
FunctionDeclaration,
isConstant,
isConstantFn,
AbiOutputParameter,
EvmType,
TupleType,
EvmOutputType,
} from "typechain";
import { values } from "lodash";

export function codegen(contracts: Contract[]) {
const template = `
/// <reference types="truffle-typings" />
import BN from "bn.js";
${contracts.map(generateContractInterface).join("\n")}
${contracts.map(generateContractInstanceInterface).join("\n")}
`;

return template;
}

export function generateArtifactHeaders(contracts: Contract[]): string {
return `
/// <reference types="truffle-typings" />
import * as TruffleContracts from ".";
declare global {
namespace Truffle {
interface Artifacts {
${contracts
.map(f => `require(name: "${f.name}"): TruffleContracts.${f.name}Contract;`)
.join("\n")}
}
}
}
`;
}

function generateContractInterface(c: Contract): string {
return `
export interface ${c.name}Contract extends Truffle.Contract<${c.name}Instance> {
${
c.constructor && c.constructor[0]
? `"new"(${generateInputTypes(
c.constructor[0].inputs,
)} meta?: Truffle.TransactionDetails): Promise<${c.name}Instance>;`
: `"new"(meta?: Truffle.TransactionDetails): Promise<${c.name}Instance>;`
}
}
`;
}

function generateContractInstanceInterface(c: Contract): string {
return `
export interface ${c.name}Instance extends Truffle.ContractInstance {
${values(c.functions)
.map(v => v[0])
.map(generateFunction)
.join("\n")}
}
`;
}

function generateFunction(fn: FunctionDeclaration): string {
if (isConstant(fn) || isConstantFn(fn)) {
return generateConstantFunction(fn);
}

return `
${fn.name}: {
(${generateInputTypes(
fn.inputs,
)} txDetails?: Truffle.TransactionDetails): Promise<Truffle.TransactionResponse>;
call(${generateInputTypes(
fn.inputs,
)} txDetails?: Truffle.TransactionDetails): Promise<${generateOutputTypes(fn.outputs)}>;
sendTransaction(${generateInputTypes(
fn.inputs,
)} txDetails?: Truffle.TransactionDetails): Promise<string>;
estimateGas(${generateInputTypes(
fn.inputs,
)} txDetails?: Truffle.TransactionDetails): Promise<number>;
}
`;
}

function generateConstantFunction(fn: FunctionDeclaration): string {
return `
${fn.name}(${generateInputTypes(
fn.inputs,
)} txDetails?: Truffle.TransactionDetails): Promise<${generateOutputTypes(fn.outputs)}>;
`;
}

function generateInputTypes(input: Array<AbiParameter>): string {
if (input.length === 0) {
return "";
}
return (
input
.map((input, index) => `${input.name || `arg${index}`}: ${generateInputType(input.type)}`)
.join(", ") + ", "
);
}

function generateOutputTypes(outputs: Array<AbiOutputParameter>): string {
if (outputs.length === 1) {
return generateOutputType(outputs[0].type);
} else {
return `[${outputs.map(param => generateOutputType(param.type)).join(", ")}]`;
}
}

function generateInputType(evmType: EvmType): string {
switch (evmType.type) {
case "integer":
return "number | BN | string";
case "uinteger":
return "number | BN | string";
case "address":
return "string | BN";
case "bytes":
return "string | BN";
case "dynamic-bytes":
return "string";
case "array":
return `(${generateInputType(evmType.itemType)})[]`;
case "boolean":
return "boolean";
case "string":
return "string";
case "tuple":
return generateTupleType(evmType, generateInputType);
}
}

function generateOutputType(evmType: EvmOutputType): string {
switch (evmType.type) {
case "integer":
return "BN";
case "uinteger":
return "BN";
case "address":
return "string";
case "void":
return "void";
case "bytes":
case "dynamic-bytes":
return "string";
case "array":
return `(${generateOutputType(evmType.itemType)})[]`;
case "boolean":
return "boolean";
case "string":
return "string";
case "tuple":
return generateTupleType(evmType, generateOutputType);
}
}

function generateTupleType(tuple: TupleType, generator: (evmType: EvmType) => string) {
return (
"{" +
tuple.components
.map(component => `${component.name}: ${generator(component.type)}`)
.join(", ") +
"}"
);
}
53 changes: 53 additions & 0 deletions packages/typechain-target-truffle-v5/lib/index.ts
@@ -0,0 +1,53 @@
import { Contract, getFilename, extractAbi, parse } from "typechain";
import { TsGeneratorPlugin, TContext, TFileDesc } from "ts-generator";
import { join, resolve } from "path";

import { codegen, generateArtifactHeaders } from "./generation";

export interface ITruffleCfg {
outDir?: string;
}

const DEFAULT_OUT_PATH = "./types/truffle-contracts/";

export default class Truffle extends TsGeneratorPlugin {
name = "Truffle";

private readonly outDirAbs: string;
private contracts: Contract[] = [];

constructor(ctx: TContext<ITruffleCfg>) {
super(ctx);

const { cwd, rawConfig } = ctx;

this.outDirAbs = resolve(cwd, rawConfig.outDir || DEFAULT_OUT_PATH);
}

transformFile(file: TFileDesc): TFileDesc | void {
const abi = extractAbi(file.contents);
const isEmptyAbi = abi.length === 0;
if (isEmptyAbi) {
return;
}

const name = getFilename(file.path);

const contract = parse(abi, name);

this.contracts.push(contract);
}

afterRun(): TFileDesc[] {
return [
{
path: join(this.outDirAbs, "index.d.ts"),
contents: codegen(this.contracts),
},
{
path: join(this.outDirAbs, "merge.d.ts"),
contents: generateArtifactHeaders(this.contracts),
},
];
}
}
29 changes: 29 additions & 0 deletions packages/typechain-target-truffle-v5/package.json
@@ -0,0 +1,29 @@
{
"name": "typechain-target-truffle-v5",
"description": "TypeChain target with truffle v5 support",
"keywords": [
"ethereum",
"typescript",
"bindings",
"truffle"
],
"version": "1.0.2",
"license": "MIT",
"repository": "https://github.com/ethereum-ts/Typechain",
"devDependencies": {
"truffle": "^5.1.1",
"truffle-typings": "^1.0.8"
},
"dependencies": {
"lodash": "^4.17.15",
"@types/bn.js": "4.11.5"
},
"peerDependencies": {
"typechain": "^1.0.0"
},
"scripts": {
"build": "rm -rf ./dist && cp -R '../../dist/typechain-target-truffle-v5/lib' ./dist/",
"prepublishOnly": "cd .. && yarn prepublishOnly"
},
"main": "./dist/index.js"
}
2 changes: 1 addition & 1 deletion packages/typechain-target-truffle/package.json
@@ -1,6 +1,6 @@
{
"name": "typechain-target-truffle",
"description": "TypeChain target with truffle support",
"description": "TypeChain target with truffle v4 support",
"keywords": [
"ethereum",
"typescript",
Expand Down

0 comments on commit f406c18

Please sign in to comment.