Skip to content

Commit

Permalink
Merge pull request #152 from JamesLefrere/feature/improve-event-typin…
Browse files Browse the repository at this point in the history
…g-and-update-web3

Improve event typing and update `web3` for the `web3-1.0.0` target
  • Loading branch information
krzkaczor authored May 24, 2019
2 parents 158fc77 + 44e6062 commit be25b3e
Show file tree
Hide file tree
Showing 7 changed files with 346 additions and 235 deletions.
26 changes: 7 additions & 19 deletions lib/targets/web3/generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import {

export function codegen(contract: Contract) {
const template = `
import { Contract, ContractOptions, Options } from "web3-eth-contract";
import { Block } from "web3-eth";
import BN from "bn.js";
import { Contract, ContractOptions, EventOptions } from "web3-eth-contract";
import { EventLog } from "web3-core";
import { EventEmitter } from "events";
import { Callback, TransactionObject } from "./types";
import { Callback, TransactionObject, ContractEvent } from "./types";
export class ${contract.name} extends Contract {
constructor(jsonInterface: any[], address?: string, options?: ContractOptions);
Expand All @@ -37,11 +37,7 @@ export function codegen(contract: Contract) {
events: {
${contract.events.map(generateEvents).join("\n")}
allEvents: (
options?: {
filter?: object;
fromBlock?: number | string;
topics?: (null|string)[];
},
options?: EventOptions,
cb?: Callback<EventLog>
) => EventEmitter;
};
Expand Down Expand Up @@ -86,15 +82,7 @@ function generateOutputTypes(outputs: Array<AbiParameter>): string {
}

function generateEvents(event: EventDeclaration) {
return `
${event.name}(
options?: {
filter?: object;
fromBlock?: number | string;
topics?: (null|string)[];
},
cb?: Callback<EventLog>): EventEmitter;
`;
return `${event.name}: ContractEvent<${generateOutputTypes(event.inputs)}>`;
}

function generateInputType(evmType: EvmType): string {
Expand Down Expand Up @@ -124,9 +112,9 @@ function generateInputType(evmType: EvmType): string {
function generateOutputType(evmType: EvmType): string {
switch (evmType.constructor) {
case IntegerType:
return "string";
return "BN";
case UnsignedIntegerType:
return "string";
return "BN";
case AddressType:
return "string";
case VoidType:
Expand Down
25 changes: 19 additions & 6 deletions lib/targets/web3/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Contract } from "../../parser/abiParser";
import { TsGeneratorPlugin, TContext, TFileDesc } from "ts-generator";
import { join } from "path";
import { extractAbi, parse } from "../../parser/abiParser";
Expand Down Expand Up @@ -46,17 +45,31 @@ export class Web3 extends TsGeneratorPlugin {
{
path: join(this.outDirAbs, "types.d.ts"),
contents: `
import { Transaction } from "web3-core";
import { EventLog } from "web3-core";
import BN from "bn.js";
import { EstimateGasOptions, EventOptions } from "web3-eth-contract";
import { EventEmitter } from "events";
// @ts-ignore
import PromiEvent from "web3-core-promievent";
export type Callback<T> = (error: Error, result: T) => void;
export interface TransactionObject<T> {
arguments: any[];
call(tx?: Transaction): Promise<T>;
send(tx?: Transaction): PromiEvent<T>;
estimateGas(tx?: Transaction): Promise<number>;
call(options?: EstimateGasOptions): Promise<T>;
send(options?: EstimateGasOptions): PromiEvent<T>;
estimateGas(options?: EstimateGasOptions): Promise<number>;
encodeABI(): string;
}`,
}
export interface ContractEventLog<T> extends EventLog {
returnValues: T;
}
export interface ContractEventEmitter<T> extends EventEmitter {
on(event: 'data' | 'changed', listener: (event: ContractEventLog<T>) => void): this;
on(event: 'error', listener: (error: Error) => void): this;
}
export type ContractEvent<T> = (
options?: EventOptions,
cb?: Callback<ContractEventLog<T>>
) => ContractEventEmitter<T>;`,
},
];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { deployContract, accounts } from "./web3";
import { DumbContract } from "./types/web3-contracts/DumbContract";
import { deployContract, accounts, isBigNumber } from "./web3";
import { ContractWithOverloads } from "./types/web3-contracts/ContractWithOverloads";

import { expect } from "chai";
import { ContractWithOverloads } from "./types/web3-contracts/ContractWithOverloads";

describe("ContractWithOverloads", () => {
it("should work", async () => {
const contract = (await deployContract("ContractWithOverloads")) as ContractWithOverloads;
const contract = await deployContract<ContractWithOverloads>("ContractWithOverloads");

expect(await contract.methods.counter().call({ from: accounts[0] })).to.be.deep.eq("0");
const res = await contract.methods.counter().call({ from: accounts[0] });
expect(isBigNumber(res)).to.be.true;
expect(res.toString()).to.be.eq("0");
});
});
37 changes: 26 additions & 11 deletions test/integration/targets/web3-1.0.0/DumbContract.spec.web3.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deployContract, accounts } from "./web3";
import { deployContract, accounts, isBigNumber } from "./web3";
import { DumbContract } from "./types/web3-contracts/DumbContract";

import { expect } from "chai";
Expand All @@ -7,10 +7,11 @@ describe("DumbContract", () => {
it("should work", async () => {
const contract: DumbContract = await deployContract<DumbContract>("DumbContract");

expect(await contract.methods.returnAll().call({ from: accounts[0] })).to.be.deep.eq({
"0": "0",
"1": "5",
});
const res = await contract.methods.returnAll().call({ from: accounts[0] });
expect(isBigNumber(res[0])).to.be.true;
expect(isBigNumber(res[1])).to.be.true;
expect(res[0].toString()).to.be.eq("0");
expect(res[1].toString()).to.be.eq("5");
});

it("should have an address", async () => {
Expand All @@ -23,16 +24,26 @@ describe("DumbContract", () => {
const contract = await deployContract<DumbContract>("DumbContract");

await contract.methods.countup(2).send({ from: accounts[0] });
expect(await contract.methods.counter().call()).to.be.eq("2");
const withNumber = await contract.methods.counter().call();
expect(isBigNumber(withNumber)).to.be.true;
expect(withNumber.toString()).to.be.eq("2");

await contract.methods.countup("2").send({ from: accounts[0] });
expect(await contract.methods.counter().call()).to.be.eq("4");
const withString = await contract.methods.counter().call();
expect(isBigNumber(withString)).to.be.true;
expect(withString.toString()).to.be.eq("4");
});

it("should allow to pass signed values in multiple ways", async () => {
const contract = await deployContract<DumbContract>("DumbContract");

expect(await contract.methods.returnSigned(2).call()).to.be.eq("2");
expect(await contract.methods.returnSigned("2").call()).to.be.eq("2");
const withNumber = await contract.methods.returnSigned(2).call();
expect(isBigNumber(withNumber)).to.be.true;
expect(withNumber.toString()).to.be.eq("2");

const withString = await contract.methods.returnSigned("2").call();
expect(isBigNumber(withString)).to.be.true;
expect(withString.toString()).to.be.eq("2");
});

it("should allow to pass address values in multiple ways", async () => {
Expand Down Expand Up @@ -65,7 +76,11 @@ describe("DumbContract", () => {
const contract = await deployContract<DumbContract>("DumbContract");

const res = await contract.methods.callWithArray2(["1", 2]).call();
expect(res).to.be.deep.eq(["1", "2"]);
expect(res.length).to.be.eq(2);
expect(isBigNumber(res[0])).to.be.true;
expect(isBigNumber(res[1])).to.be.true;
expect(res[0].toString()).to.be.eq("1");
expect(res[1].toString()).to.be.eq("2");
});

it("should allow to pass strings ", async () => {
Expand All @@ -80,6 +95,6 @@ describe("DumbContract", () => {
const contractClone = await contract.clone();

expect(contractClone).not.to.be.eq(contract);
expect(contractClone.options.address).to.be.eq(contract.options.address);
expect(contractClone.options.address).to.be.undefined;
});
});
4 changes: 2 additions & 2 deletions test/integration/targets/web3-1.0.0/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
"web3": "^1.0.0-beta.48"
"web3": "^1.0.0-beta.54"
},
"devDependencies": {
"@types/bn.js": "^4.11.1",
Expand All @@ -17,7 +17,7 @@
},
"scripts": {
"tsc": "tsc --noEmit",
"mocha": "NODE_ENV=test mocha --require ts-node/register.js './**/*.spec.web3.ts'",
"mocha": "NODE_ENV=test mocha --require ts-node/register.js './**/*.spec.web3.ts' --timeout 5000",
"test": "yarn tsc && yarn mocha"
}
}
10 changes: 9 additions & 1 deletion test/integration/targets/web3-1.0.0/web3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export let web3: Web3;
export let accounts: string[];

export async function createNewBlockchain() {
const web3 = new Web3(ganache.provider());
const web3 = new Web3(ganache.provider(), undefined, {
transactionConfirmationBlocks: 1,
});
const accounts = await web3.eth.getAccounts();
return { web3, accounts };
}
Expand All @@ -36,3 +38,9 @@ export async function deployContract<T>(contractName: string): Promise<T> {
gas: GAS_LIMIT_STANDARD,
}) as any)) as T;
}

export function isBigNumber(object: any): boolean {
// Cribbed from web3-utils until BNs/BigNumbers are resolved in web3
// https://github.com/ethereum/web3.js/issues/2468
return object && object.constructor && object.constructor.name === "BigNumber";
}
Loading

0 comments on commit be25b3e

Please sign in to comment.