From 566ed658e6717014c8593f723a9d438de9e1b677 Mon Sep 17 00:00:00 2001 From: Federico Date: Tue, 25 Sep 2018 17:11:55 +0200 Subject: [PATCH 01/10] added getPastEvents method --- packages/api/.gitignore | 2 +- packages/api/package.json | 2 +- packages/api/partials/typed_params.handlebars | 2 +- packages/api/src/baseContract.ts | 17 ++++++++++++++++- packages/api/template.handlebars | 16 ++-------------- packages/api/test/contracts.test.ts | 13 +++++++++++-- 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/packages/api/.gitignore b/packages/api/.gitignore index 1ab3d818d..7f31e16d5 100644 --- a/packages/api/.gitignore +++ b/packages/api/.gitignore @@ -1,6 +1,6 @@ coverage .tmp -src/generated +src/contracts/models dist lib node_modules diff --git a/packages/api/package.json b/packages/api/package.json index 2f96c0e12..20e6ddddf 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -13,7 +13,7 @@ "test": "jest", "tsc:watch": "rm -rf dist; tsc -w --outDir './dist'", "lint": "eslint src --ext ts --ignore-path .gitignore --fix", - "abi-gen": "node src/abi-extractor.js && rm -rf src/generated && ts-node abi-gen.ts --abis './.tmp/*.json' -o src/generated --template './template.handlebars' --partials './partials/*.handlebars'" + "abi-gen": "rm -rf src/contracts/models && ts-node abi-gen.ts --abis './.tmp/*.json' -o src/contracts/models --template './template.handlebars' --partials './partials/*.handlebars'" }, "files": [ "dist" diff --git a/packages/api/partials/typed_params.handlebars b/packages/api/partials/typed_params.handlebars index c100e58f7..bbbdef29b 100644 --- a/packages/api/partials/typed_params.handlebars +++ b/packages/api/partials/typed_params.handlebars @@ -1,3 +1,3 @@ {{#each inputs}} - {{name}}: {{#parameterType type components}}{{/parameterType}}, +{{name}}: {{#parameterType type components}}{{/parameterType}}, {{/each}} diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index adb71bee3..a4e43a266 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -1,6 +1,21 @@ -export default class BaseContract { +interface EventFilter { + [key: string]: string +} + +interface EventOptions { + filter?: EventFilter + fromBlock?: number + toBlock?: number + topics?: string[] +} + +export default class BaseContract { public readonly rawWeb3Contract: any constructor(web3: any, address: string, abi: any) { this.rawWeb3Contract = new web3.eth.Contract(abi, address) } + + public async getPastEvents(eventName: Events, options?: EventOptions) { + return this.rawWeb3Contract.getPastEvents(eventName, options || {}) + } } diff --git a/packages/api/template.handlebars b/packages/api/template.handlebars index 8819e6511..bcceb13ca 100644 --- a/packages/api/template.handlebars +++ b/packages/api/template.handlebars @@ -1,13 +1,6 @@ /* eslint-disable */ import { BigNumber } from 'bignumber.js' -import BaseContract from '../baseContract' - -{{!-- TODO: add events --}} -{{!-- {{#if events}} -export type {{contractName}}EventArgs = -{{#each events}} - | {{@root.contractName}}{{name}}EventArgs{{#if @last}};{{/if}} -{{/each}} +import BaseContract from '../../baseContract' export enum {{contractName}}Events { {{#each events}} @@ -15,12 +8,7 @@ export enum {{contractName}}Events { {{/each}} } -{{#each events}} -{{> event}} - -{{/each}} -{{/if}} --}} -export class {{contractName}} extends BaseContract { +export class {{contractName}} extends BaseContract<{{contractName}}Events> { public constructor(web3: any, address: string) { const abi = {{{getAbi ctor events methods}}} super(web3, address, abi); diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index cc360159e..3629b2558 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -1,6 +1,10 @@ import Web3 = require('web3') -import { Vault } from '../src/generated/vault' -import { VaultFactory } from '../src/generated/vault_factory' +import 'jest' +import { Vault } from '../src/contracts/models/vault' +import { + VaultFactory, + VaultFactoryEvents +} from '../src/contracts/models/vault_factory' describe('generated contract', () => { let web3 @@ -54,6 +58,11 @@ describe('generated contract', () => { ) extendedExpect(receipt.transactionHash).toBeHash() + const eventLog = await vaultFactory.getPastEvents( + VaultFactoryEvents.VaultCreated, + { fromBlock: 0, toBlock: 'latest' } + ) + expect(eventLog[eventLog.length - 1].returnValues.name).toEqual(vaultName) }) describe('payable methods', async () => { let vaultInstance From f8077835d29a30967c911fd2942652f73e983f3c Mon Sep 17 00:00:00 2001 From: Federico Date: Tue, 25 Sep 2018 17:47:09 +0200 Subject: [PATCH 02/10] added allEvents function --- packages/api/src/baseContract.ts | 11 +++++++- packages/api/test/contracts.test.ts | 42 +++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index a4e43a266..51812e8b6 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -1,3 +1,5 @@ +import { EventEmitter, EventLog } from 'web3/types' + interface EventFilter { [key: string]: string } @@ -15,7 +17,14 @@ export default class BaseContract { this.rawWeb3Contract = new web3.eth.Contract(abi, address) } - public async getPastEvents(eventName: Events, options?: EventOptions) { + public getPastEvents( + eventName: Events, + options?: EventOptions + ): Promise { return this.rawWeb3Contract.getPastEvents(eventName, options || {}) } + + public allEvents(options?: EventOptions): Promise { + return this.rawWeb3Contract.events.allEvents(options || {}) + } } diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index 3629b2558..b227df970 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -36,11 +36,13 @@ describe('generated contract', () => { '0x7ce6e371085cb611fb46d5065397223ef2f952ff' ) }) + it('constant method', async () => { const registry = '0xf7cBB0849d4a8ec5aB4650030FA776c00Eb52dA7' const res = await vaultFactory.getRegistry() expect(res).toEqual(registry) }) + it('createVault', async () => { const vaultName = Math.random() .toString(36) @@ -58,12 +60,8 @@ describe('generated contract', () => { ) extendedExpect(receipt.transactionHash).toBeHash() - const eventLog = await vaultFactory.getPastEvents( - VaultFactoryEvents.VaultCreated, - { fromBlock: 0, toBlock: 'latest' } - ) - expect(eventLog[eventLog.length - 1].returnValues.name).toEqual(vaultName) }) + describe('payable methods', async () => { let vaultInstance beforeAll(async () => { @@ -97,5 +95,39 @@ describe('generated contract', () => { ) }) }) + + describe('event functions', () => { + describe('getPastEvents', () => { + it('returns past logs for the specified event', async () => { + const eventLog = await vaultFactory.getPastEvents( + VaultFactoryEvents.VaultCreated, + { fromBlock: 0, toBlock: 'latest' } + ) + expect(Array.isArray(eventLog)).toBe(true) + }) + }) + // TODO: improve the test if possible + describe('allEvents', () => { + it('returns an event emitter to subscribe to all events of the smart contracts', async () => { + const filterOptions = { + fromBlock: 0, + toBlock: 'latest' + } + const filterCallback = (err, event) => + err ? console.error(err) : console.log(event) + const events = await vaultFactory.allEvents( + filterOptions, + filterCallback + ) + expect(events.callback).toEqual(filterCallback) + }) + }) + // describe('', () => { + // it('', async () => {}) + // }) + // describe('', () => { + // it('', async () => {}) + // }) + }) }) }) From bac8ec134e990d6bb85af86d767d3b84c36442fb Mon Sep 17 00:00:00 2001 From: Federico Date: Tue, 25 Sep 2018 18:10:35 +0200 Subject: [PATCH 03/10] added once, missing test --- packages/api/src/baseContract.ts | 15 +++++++++++++-- packages/api/test/contracts.test.ts | 7 ++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index 51812e8b6..09a756911 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -24,7 +24,18 @@ export default class BaseContract { return this.rawWeb3Contract.getPastEvents(eventName, options || {}) } - public allEvents(options?: EventOptions): Promise { - return this.rawWeb3Contract.events.allEvents(options || {}) + public allEvents( + options?: EventOptions, + cb?: Function + ): Promise { + return this.rawWeb3Contract.events.allEvents(options || {}, cb) + } + // TODO: write test for once + public once( + eventName: Events, + options?: EventOptions, + cb?: Function + ): Promise { + return this.rawWeb3Contract.once(eventName, options || {}, cb) } } diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index b227df970..3cbfbe147 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -115,11 +115,8 @@ describe('generated contract', () => { } const filterCallback = (err, event) => err ? console.error(err) : console.log(event) - const events = await vaultFactory.allEvents( - filterOptions, - filterCallback - ) - expect(events.callback).toEqual(filterCallback) + const events = await vaultFactory.allEvents(filterOptions) + expect(events) }) }) // describe('', () => { From 8ae8c5a3c1248e34f84cacc1838a9ecef0baa84d Mon Sep 17 00:00:00 2001 From: Federico Date: Tue, 25 Sep 2018 18:41:36 +0200 Subject: [PATCH 04/10] modified event partial --- packages/api/partials/event.handlebars | 8 ++++---- packages/api/partials/txFunction.handlebars | 2 +- packages/api/template.handlebars | 9 +++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/api/partials/event.handlebars b/packages/api/partials/event.handlebars index 61d523ca2..56750a8cc 100644 --- a/packages/api/partials/event.handlebars +++ b/packages/api/partials/event.handlebars @@ -1,5 +1,5 @@ -export interface {{@root.contractName}}{{name}}EventArgs extends DecodedLogArgs { - {{#each inputs}} - {{name}}: {{#returnType type components}}{{/returnType}}; - {{/each}} +public {{this.name}}Event( + {{> typed_params inputs=inputs}} +) { + return this.rawWeb3Contract.events.{{this.name}}(({{> params inputs=inputs}})) } diff --git a/packages/api/partials/txFunction.handlebars b/packages/api/partials/txFunction.handlebars index 514a7e1d2..490f0bdd4 100644 --- a/packages/api/partials/txFunction.handlebars +++ b/packages/api/partials/txFunction.handlebars @@ -1,3 +1,3 @@ -public async {{this.tsName}}({{> typed_params inputs=inputs}}): Promise<{{> return_type outputs=outputs}}> { +public {{this.tsName}}({{> typed_params inputs=inputs}}): Promise<{{> return_type outputs=outputs}}> { return this.rawWeb3Contract.methods.{{this.tsName}}({{> params inputs=inputs}}) } diff --git a/packages/api/template.handlebars b/packages/api/template.handlebars index bcceb13ca..2955eb0b8 100644 --- a/packages/api/template.handlebars +++ b/packages/api/template.handlebars @@ -2,11 +2,13 @@ import { BigNumber } from 'bignumber.js' import BaseContract from '../../baseContract' +{{#if events}} export enum {{contractName}}Events { {{#each events}} {{name}} = '{{name}}', {{/each}} } +{{/if}} export class {{contractName}} extends BaseContract<{{contractName}}Events> { public constructor(web3: any, address: string) { @@ -30,6 +32,7 @@ export class {{contractName}} extends BaseContract<{{contractName}}Events> { } public static address: string + {{#each methods}} {{#this.constant}} {{> constantFunction contractName=../contractName}} @@ -38,6 +41,12 @@ export class {{contractName}} extends BaseContract<{{contractName}}Events> { {{> txFunction contractName=../contractName}} {{/this.constant}} {{/each}} + {{#if events}} + {{#each events}} + {{log this}} + {{> event contractName=../contractName}} + {{/each}} + {{/if}} static isDeployed() { return !!this.address From 0b70bbc1a7ead11e6ce72d6b0bccf6d408de91ce Mon Sep 17 00:00:00 2001 From: Federico Date: Tue, 25 Sep 2018 18:58:56 +0200 Subject: [PATCH 05/10] fixed event partial --- packages/api/partials/event.handlebars | 5 +++-- packages/api/partials/txFunction.handlebars | 2 +- packages/api/partials/typed_params.handlebars | 2 +- packages/api/src/baseContract.ts | 4 ++-- packages/api/template.handlebars | 2 +- packages/api/test/contracts.test.ts | 12 +++++++----- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/api/partials/event.handlebars b/packages/api/partials/event.handlebars index 56750a8cc..4d89e4ebb 100644 --- a/packages/api/partials/event.handlebars +++ b/packages/api/partials/event.handlebars @@ -1,5 +1,6 @@ public {{this.name}}Event( - {{> typed_params inputs=inputs}} + options?: EventOptions, + cb?: Function ) { - return this.rawWeb3Contract.events.{{this.name}}(({{> params inputs=inputs}})) + return this.rawWeb3Contract.events.{{this.name}}(options || {}, cb) } diff --git a/packages/api/partials/txFunction.handlebars b/packages/api/partials/txFunction.handlebars index 490f0bdd4..514a7e1d2 100644 --- a/packages/api/partials/txFunction.handlebars +++ b/packages/api/partials/txFunction.handlebars @@ -1,3 +1,3 @@ -public {{this.tsName}}({{> typed_params inputs=inputs}}): Promise<{{> return_type outputs=outputs}}> { +public async {{this.tsName}}({{> typed_params inputs=inputs}}): Promise<{{> return_type outputs=outputs}}> { return this.rawWeb3Contract.methods.{{this.tsName}}({{> params inputs=inputs}}) } diff --git a/packages/api/partials/typed_params.handlebars b/packages/api/partials/typed_params.handlebars index bbbdef29b..e4423c5f9 100644 --- a/packages/api/partials/typed_params.handlebars +++ b/packages/api/partials/typed_params.handlebars @@ -1,3 +1,3 @@ {{#each inputs}} -{{name}}: {{#parameterType type components}}{{/parameterType}}, +{{name}}: {{#parameterType type components}}{{/parameterType}}{{#if @last}}{{else}},{{/if}} {{/each}} diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index 09a756911..77252db03 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -1,10 +1,10 @@ import { EventEmitter, EventLog } from 'web3/types' -interface EventFilter { +export interface EventFilter { [key: string]: string } -interface EventOptions { +export interface EventOptions { filter?: EventFilter fromBlock?: number toBlock?: number diff --git a/packages/api/template.handlebars b/packages/api/template.handlebars index 2955eb0b8..843c67643 100644 --- a/packages/api/template.handlebars +++ b/packages/api/template.handlebars @@ -1,6 +1,6 @@ /* eslint-disable */ import { BigNumber } from 'bignumber.js' -import BaseContract from '../../baseContract' +import BaseContract, { EventFilter, EventOptions} from '../../baseContract' {{#if events}} export enum {{contractName}}Events { diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index 3cbfbe147..2b37e20a6 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -1,5 +1,5 @@ import Web3 = require('web3') -import 'jest' +import 'jest' // TODO: remove this import { Vault } from '../src/contracts/models/vault' import { VaultFactory, @@ -119,12 +119,14 @@ describe('generated contract', () => { expect(events) }) }) - // describe('', () => { - // it('', async () => {}) - // }) - // describe('', () => { + // describe('once', () => { // it('', async () => {}) // }) + fdescribe('contract event', () => { + it('works', async () => { + const event = vaultFactory.VaultFactoryEvent() + }) + }) }) }) }) From a6fbde2e36ec08d4ffdfeea42fb340a2218dc847 Mon Sep 17 00:00:00 2001 From: Federico Date: Wed, 26 Sep 2018 17:46:35 +0200 Subject: [PATCH 06/10] wip --- packages/api/package.json | 6 +++ packages/api/prova.ts | 75 +++++++++++++++++++++++++++++ packages/api/src/baseContract.ts | 3 +- packages/api/template.handlebars | 1 - packages/api/test/contracts.test.ts | 26 +++++++--- packages/api/tsconfig.json | 4 +- yarn.lock | 16 +++++- 7 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 packages/api/prova.ts diff --git a/packages/api/package.json b/packages/api/package.json index 20e6ddddf..55e36d388 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -12,15 +12,20 @@ "tsc": "rm -rf dist/* && tsc --outDir './dist'", "test": "jest", "tsc:watch": "rm -rf dist; tsc -w --outDir './dist'", + "ganache": "npx ganache-cli -p 8545 -i 5777 -m \"${npm_package_config_mnemonic}\"", "lint": "eslint src --ext ts --ignore-path .gitignore --fix", "abi-gen": "rm -rf src/contracts/models && ts-node abi-gen.ts --abis './.tmp/*.json' -o src/contracts/models --template './template.handlebars' --partials './partials/*.handlebars'" }, + "config": { + "mnemonic": "lemon scrub wasp bracket town boat property sadness layer taxi butter audit" + }, "files": [ "dist" ], "devDependencies": { "@0xproject/abi-gen": "^1.0.9", "@types/jest": "^23.3.2", + "@types/web3": "^1.0.6", "bignumber.js": "^7.2.1", "chalk": "^2.4.1", "eslint-plugin-typescript": "^0.12.0", @@ -36,6 +41,7 @@ "@rigoblock/contracts": "^0.3.2", "@types/node": "^9.6.6", "bignumber.js": "^5.0.0", + "ganache-cli": "7.0.0-beta.0", "handlebars": "^4.0.12", "typechain": "^0.2.2", "web3": "1.0.0-beta.36", diff --git a/packages/api/prova.ts b/packages/api/prova.ts new file mode 100644 index 000000000..850f84554 --- /dev/null +++ b/packages/api/prova.ts @@ -0,0 +1,75 @@ +import Web3 = require('web3') +import { + VaultFactory, + VaultFactoryEvents +} from './src/contracts/models/vault_factory' + +// const getData = async () => { +// const web3 = new Web3( +// new Web3.providers.WebsocketProvider('ws://localhost:8545') +// ) +// console.log('here') +// const accounts = await web3.eth.getAccounts() +// const vaultFactory = await VaultFactory.createAndValidate( +// web3, +// '0x7ce6e371085cb611fb46d5065397223ef2f952ff' +// ) +// const filterOptions: any = { +// fromBlock: 0, +// toBlock: 'latest' +// } +// const filterCallback = (err, event) => +// err ? console.error(err) : console.log(event) +// const events = await vaultFactory.allEvents(filterOptions, filterCallback) +// // --------------------- +// const vaultName = Math.random() +// .toString(36) +// .substring(2, 7) +// const txOptions = { +// from: accounts[0] +// } +// const gasPrice = await web3.eth.getGasPrice() +// const gasEstimate = await vaultFactory +// .createVault(vaultName, 'ASD') +// .then(obj => obj.estimateGas(txOptions)) +// const receipt = await vaultFactory +// .createVault(vaultName, 'ASD') +// .then(obj => obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 })) +// } +const getData = async () => { + const web3 = new Web3( + new Web3.providers.WebsocketProvider('ws://localhost:8545') + ) + console.log('here') + const accounts = await web3.eth.getAccounts() + const vaultFactory = await VaultFactory.createAndValidate( + web3, + '0x7ce6e371085cb611fb46d5065397223ef2f952ff' + ) + const filterOptions: any = { + fromBlock: 0, + toBlock: 'latest' + } + const filterCallback = (err, event) => + err ? console.error(err) : console.log(event) + const events = await vaultFactory.VaultCreatedEvent( + filterOptions, + filterCallback + ) + // --------------------- + const vaultName = Math.random() + .toString(36) + .substring(2, 7) + const txOptions = { + from: accounts[0] + } + const gasPrice = await web3.eth.getGasPrice() + const gasEstimate = await vaultFactory + .createVault('staminchia', 'ASD') + .then(obj => obj.estimateGas(txOptions)) + const receipt = await vaultFactory + .createVault('staminchia', 'ASD') + .then(obj => obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 })) +} + +getData() diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index 77252db03..101bb8a70 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -1,3 +1,4 @@ +import Web3 = require('web3') import { EventEmitter, EventLog } from 'web3/types' export interface EventFilter { @@ -13,7 +14,7 @@ export interface EventOptions { export default class BaseContract { public readonly rawWeb3Contract: any - constructor(web3: any, address: string, abi: any) { + constructor(web3: Web3, address: string, abi: any) { this.rawWeb3Contract = new web3.eth.Contract(abi, address) } diff --git a/packages/api/template.handlebars b/packages/api/template.handlebars index 843c67643..ab0b4f468 100644 --- a/packages/api/template.handlebars +++ b/packages/api/template.handlebars @@ -43,7 +43,6 @@ export class {{contractName}} extends BaseContract<{{contractName}}Events> { {{/each}} {{#if events}} {{#each events}} - {{log this}} {{> event contractName=../contractName}} {{/each}} {{/if}} diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index 2b37e20a6..ba0c62694 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -1,5 +1,6 @@ import Web3 = require('web3') import 'jest' // TODO: remove this +import { EventEmitter } from 'events' import { Vault } from '../src/contracts/models/vault' import { VaultFactory, @@ -12,7 +13,7 @@ describe('generated contract', () => { let accounts let txOptions beforeAll(async () => { - web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) + web3 = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8545')) accounts = await web3.eth.getAccounts() extendedExpect = expect as any }) @@ -97,6 +98,7 @@ describe('generated contract', () => { }) describe('event functions', () => { + class WebsocketMock extends EventEmitter {} describe('getPastEvents', () => { it('returns past logs for the specified event', async () => { const eventLog = await vaultFactory.getPastEvents( @@ -107,7 +109,11 @@ describe('generated contract', () => { }) }) // TODO: improve the test if possible - describe('allEvents', () => { + fdescribe('allEvents', () => { + // beforeEach(async () => { + // jest.resetModules() + // jest.doMock() + // }) it('returns an event emitter to subscribe to all events of the smart contracts', async () => { const filterOptions = { fromBlock: 0, @@ -115,16 +121,24 @@ describe('generated contract', () => { } const filterCallback = (err, event) => err ? console.error(err) : console.log(event) - const events = await vaultFactory.allEvents(filterOptions) - expect(events) + const events = await vaultFactory.allEvents( + filterOptions, + filterCallback + ) + console.log(events.options.requestManager) }) }) // describe('once', () => { // it('', async () => {}) // }) - fdescribe('contract event', () => { + describe.skip('contract event', () => { it('works', async () => { - const event = vaultFactory.VaultFactoryEvent() + const event = vaultFactory.VaultCreatedEvent({ + fromBlock: 0, + toBlock: 'latest' + }) + console.log(event) + expect(event) }) }) }) diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index 77cc0ce8b..d9e49aace 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -9,7 +9,7 @@ "noImplicitReturns": true, "declaration": true, "sourceMap": true, - "pretty": true, - "typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"], + "pretty": true + // "typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"], } } diff --git a/yarn.lock b/yarn.lock index f82297381..c9ef1ebb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1395,6 +1395,13 @@ "@types/bn.js" "*" "@types/underscore" "*" +"@types/web3@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.6.tgz#ea6bd4591a59efa73c3399b2bf172a268630edbf" + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + "@types/yargs@10.0.2": version "10.0.2" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-10.0.2.tgz#cc4ea921877874d1261e2c44b89807bc836e1b12" @@ -7400,6 +7407,13 @@ fuse.js@^3.0.1, fuse.js@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.2.1.tgz#6320cb94ce56ec9755c89ade775bcdbb0358d425" +ganache-cli@7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-7.0.0-beta.0.tgz#9454567d731bd8f0b582e40473f2f44a16f109b3" + dependencies: + source-map-support "^0.5.0" + webpack "^3.10.0" + ganache-cli@^6.1.0: version "6.1.8" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" @@ -17200,7 +17214,7 @@ webpack@4.16.1: watchpack "^1.5.0" webpack-sources "^1.0.1" -webpack@^3.11.0: +webpack@^3.10.0, webpack@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" dependencies: From aa1682a0e48771163568903edec81409b9846b1c Mon Sep 17 00:00:00 2001 From: Federico Date: Wed, 26 Sep 2018 18:07:59 +0200 Subject: [PATCH 07/10] now only contracts with events extend the baseContract --- packages/api/src/baseContract.ts | 5 +---- packages/api/template.handlebars | 12 ++++++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index 101bb8a70..a9533e835 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -13,10 +13,7 @@ export interface EventOptions { } export default class BaseContract { - public readonly rawWeb3Contract: any - constructor(web3: Web3, address: string, abi: any) { - this.rawWeb3Contract = new web3.eth.Contract(abi, address) - } + public rawWeb3Contract: any public getPastEvents( eventName: Events, diff --git a/packages/api/template.handlebars b/packages/api/template.handlebars index ab0b4f468..c34b116ad 100644 --- a/packages/api/template.handlebars +++ b/packages/api/template.handlebars @@ -10,10 +10,18 @@ export enum {{contractName}}Events { } {{/if}} +{{#if events}} export class {{contractName}} extends BaseContract<{{contractName}}Events> { - public constructor(web3: any, address: string) { + public constructor(web3: any, address: string) { + super() +{{else}} +export class {{contractName}} { + public rawWeb3Contract: any + public constructor(web3: any, address: string) { +{{/if}} + const abi = {{{getAbi ctor events methods}}} - super(web3, address, abi); + this.rawWeb3Contract = new web3.eth.Contract(abi, address) } static async createAndValidate( From d11d4cbfa91649a5cb7e6095be4542ad68d1c3eb Mon Sep 17 00:00:00 2001 From: Federico Date: Thu, 27 Sep 2018 12:22:37 +0200 Subject: [PATCH 08/10] fixed unit tests --- packages/api/prova.ts | 12 +- packages/api/src/baseContract.ts | 5 +- packages/api/test/contracts.test.ts | 215 ++++++++++++++++------------ 3 files changed, 132 insertions(+), 100 deletions(-) diff --git a/packages/api/prova.ts b/packages/api/prova.ts index 850f84554..59542d06c 100644 --- a/packages/api/prova.ts +++ b/packages/api/prova.ts @@ -52,10 +52,10 @@ const getData = async () => { } const filterCallback = (err, event) => err ? console.error(err) : console.log(event) - const events = await vaultFactory.VaultCreatedEvent( - filterOptions, - filterCallback - ) + const events = await vaultFactory.VaultCreatedEvent(filterOptions, undefined) + events.on('data', function(event) { + console.log(event) // same results as the optional callback above + }) // --------------------- const vaultName = Math.random() .toString(36) @@ -65,10 +65,10 @@ const getData = async () => { } const gasPrice = await web3.eth.getGasPrice() const gasEstimate = await vaultFactory - .createVault('staminchia', 'ASD') + .createVault(vaultName, 'ASD') .then(obj => obj.estimateGas(txOptions)) const receipt = await vaultFactory - .createVault('staminchia', 'ASD') + .createVault(vaultName, 'ASD') .then(obj => obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 })) } diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index a9533e835..121cda996 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -1,4 +1,3 @@ -import Web3 = require('web3') import { EventEmitter, EventLog } from 'web3/types' export interface EventFilter { @@ -8,7 +7,7 @@ export interface EventFilter { export interface EventOptions { filter?: EventFilter fromBlock?: number - toBlock?: number + toBlock?: number | 'latest' topics?: string[] } @@ -28,7 +27,7 @@ export default class BaseContract { ): Promise { return this.rawWeb3Contract.events.allEvents(options || {}, cb) } - // TODO: write test for once + public once( eventName: Events, options?: EventOptions, diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index ba0c62694..52bb749cd 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -1,6 +1,4 @@ import Web3 = require('web3') -import 'jest' // TODO: remove this -import { EventEmitter } from 'events' import { Vault } from '../src/contracts/models/vault' import { VaultFactory, @@ -37,108 +35,143 @@ describe('generated contract', () => { '0x7ce6e371085cb611fb46d5065397223ef2f952ff' ) }) - - it('constant method', async () => { - const registry = '0xf7cBB0849d4a8ec5aB4650030FA776c00Eb52dA7' - const res = await vaultFactory.getRegistry() - expect(res).toEqual(registry) + describe('constant methods', () => { + it('reads a constant property of the contract from the blockChain ', async () => { + const registry = '0xf7cBB0849d4a8ec5aB4650030FA776c00Eb52dA7' + const res = await vaultFactory.getRegistry() + expect(res).toEqual(registry) + }) }) - it('createVault', async () => { - const vaultName = Math.random() - .toString(36) - .substring(2, 7) - const vaultOptions = [vaultName, 'ASD'] - const gasPrice = await web3.eth.getGasPrice() - const gasEstimate = await vaultFactory // 2538415 - .createVault(...vaultOptions) - .then(obj => obj.estimateGas(txOptions)) - const receipt = await vaultFactory - .createVault(...vaultOptions) - .then(obj => - // adding value to gas estimate as it is not always correct - obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 }) - ) + describe('non constant methods', () => { + describe('non payable methods', () => { + it("writes to the blockChain, but doesn't accept ether", async () => { + const vaultName = Math.random() + .toString(36) + .substring(2, 7) + const vaultOptions = [vaultName, 'ASD'] + const gasPrice = await web3.eth.getGasPrice() + const gasEstimate = await vaultFactory // 2538415 + .createVault(...vaultOptions) + .then(obj => obj.estimateGas(txOptions)) + const receipt = await vaultFactory + .createVault(...vaultOptions) + .then(obj => + // adding value to gas estimate as it is not always correct + obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 }) + ) - extendedExpect(receipt.transactionHash).toBeHash() - }) - - describe('payable methods', async () => { - let vaultInstance - beforeAll(async () => { - const vaultName = Math.random() - .toString(36) - .substring(2, 7) - const vaultOptions = [vaultName, 'VLT'] - const gasPrice = await web3.eth.getGasPrice() - const gasEstimate = await vaultFactory - .createVault(...vaultOptions) - .then(obj => obj.estimateGas(txOptions)) - const receipt = await vaultFactory - .createVault(...vaultOptions) - .then(obj => - // adding value to gas estimate as it is not always correct - obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 }) - ) - const vaultAddress = receipt.events.VaultCreated.returnValues.vault - vaultInstance = await Vault.createAndValidate(web3, vaultAddress) + extendedExpect(receipt.transactionHash).toBeHash() + }) }) - it('buyVault', async () => { - const options = { ...txOptions, value: web3.utils.toWei('1') } - const gasPrice = await web3.eth.getGasPrice() - const gasEstimate = await vaultInstance - .buyVault() - .then(obj => obj.estimateGas(options)) - await vaultInstance - .buyVault() - .then(obj => - obj.send({ ...options, gasPrice, gas: gasEstimate + 5000 }) - ) + describe('payable methods', async () => { + let vaultInstance + beforeAll(async () => { + const vaultName = Math.random() + .toString(36) + .substring(2, 7) + const vaultOptions = [vaultName, 'VLT'] + const gasPrice = await web3.eth.getGasPrice() + const gasEstimate = await vaultFactory + .createVault(...vaultOptions) + .then(obj => obj.estimateGas(txOptions)) + const receipt = await vaultFactory + .createVault(...vaultOptions) + .then(obj => + // adding value to gas estimate as it is not always correct + obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 }) + ) + const vaultAddress = receipt.events.VaultCreated.returnValues.vault + vaultInstance = await Vault.createAndValidate(web3, vaultAddress) + }) + it('accepts an ether value', async () => { + const options = { ...txOptions, value: web3.utils.toWei('1') } + const gasPrice = await web3.eth.getGasPrice() + const gasEstimate = await vaultInstance + .buyVault() + .then(obj => obj.estimateGas(options)) + await vaultInstance + .buyVault() + .then(obj => + obj.send({ ...options, gasPrice, gas: gasEstimate + 5000 }) + ) + }) + }) + }) + }) + describe('contract events', () => { + describe('getPastEvents', () => { + it('returns past logs for the specified event', async () => { + const vaultFactory = await VaultFactory.createAndValidate( + web3, + '0x7ce6e371085cb611fb46d5065397223ef2f952ff' + ) + const eventLog = await vaultFactory.getPastEvents( + VaultFactoryEvents.VaultCreated, + { fromBlock: 0, toBlock: 'latest' } + ) + expect(Array.isArray(eventLog)).toBe(true) }) }) + describe('websocket events', () => { + const allEventsSpy = jest.fn() + const onceSpy = jest.fn() + const VaultCreatedSpy = jest.fn() + const filterOptions = { + fromBlock: 0, + toBlock: 'latest' + } + const filterCallback = (err, event) => + err ? console.error(err) : console.log(event) - describe('event functions', () => { - class WebsocketMock extends EventEmitter {} - describe('getPastEvents', () => { - it('returns past logs for the specified event', async () => { - const eventLog = await vaultFactory.getPastEvents( - VaultFactoryEvents.VaultCreated, - { fromBlock: 0, toBlock: 'latest' } - ) - expect(Array.isArray(eventLog)).toBe(true) - }) + class ContractMock { + public once(...args) { + return onceSpy(...args) + } + public events = { + allEvents: allEventsSpy, + VaultCreated: VaultCreatedSpy + } + } + const Web3Mock = { + eth: { + getCode: () => Promise.resolve('0x12345'), + Contract: ContractMock + } + } + let mockedVaultFactory + beforeEach(async () => { + const VaultFactory = require('../src/contracts/models/vault_factory') + .VaultFactory + + mockedVaultFactory = await VaultFactory.createAndValidate( + Web3Mock, + '0x7ce6e371085cb611fb46d5065397223ef2f952ff' + ) }) - // TODO: improve the test if possible - fdescribe('allEvents', () => { - // beforeEach(async () => { - // jest.resetModules() - // jest.doMock() - // }) - it('returns an event emitter to subscribe to all events of the smart contracts', async () => { - const filterOptions = { - fromBlock: 0, - toBlock: 'latest' - } - const filterCallback = (err, event) => - err ? console.error(err) : console.log(event) - const events = await vaultFactory.allEvents( + describe('allEvents', () => { + it('calls the web3 allEvents method with the specified options', async () => { + await mockedVaultFactory.allEvents(filterOptions, filterCallback) + expect(allEventsSpy).toHaveBeenCalledWith( filterOptions, filterCallback ) - console.log(events.options.requestManager) }) }) - // describe('once', () => { - // it('', async () => {}) - // }) - describe.skip('contract event', () => { - it('works', async () => { - const event = vaultFactory.VaultCreatedEvent({ - fromBlock: 0, - toBlock: 'latest' - }) - console.log(event) - expect(event) + describe('once', () => { + it('calls the web3 once function with specified options', async () => { + const options = ['VaultCreated', filterOptions, filterCallback] + await mockedVaultFactory.once(...options) + expect(onceSpy).toHaveBeenCalledWith(...options) + }) + }) + describe('contract event', () => { + it('calls the web3 event function to subscribe to a specific event', async () => { + await mockedVaultFactory.VaultCreatedEvent(filterOptions) + expect(VaultCreatedSpy).toHaveBeenCalledWith( + filterOptions, + undefined // callback is optional + ) }) }) }) From 1d1cc320ba177a1bfdb86426bef3c428234e0728 Mon Sep 17 00:00:00 2001 From: Federico Date: Thu, 27 Sep 2018 12:32:51 +0200 Subject: [PATCH 09/10] fixed return types of txFunctions --- packages/api/partials/txFunction.handlebars | 2 +- packages/api/src/baseContract.ts | 6 ++++++ packages/api/template.handlebars | 3 ++- packages/api/test/contracts.test.ts | 5 ++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/api/partials/txFunction.handlebars b/packages/api/partials/txFunction.handlebars index 514a7e1d2..cbc68026e 100644 --- a/packages/api/partials/txFunction.handlebars +++ b/packages/api/partials/txFunction.handlebars @@ -1,3 +1,3 @@ -public async {{this.tsName}}({{> typed_params inputs=inputs}}): Promise<{{> return_type outputs=outputs}}> { +public async {{this.tsName}}({{> typed_params inputs=inputs}}): Promise return_type outputs=outputs}}>> { return this.rawWeb3Contract.methods.{{this.tsName}}({{> params inputs=inputs}}) } diff --git a/packages/api/src/baseContract.ts b/packages/api/src/baseContract.ts index 121cda996..cbdbbd7d6 100644 --- a/packages/api/src/baseContract.ts +++ b/packages/api/src/baseContract.ts @@ -1,5 +1,11 @@ import { EventEmitter, EventLog } from 'web3/types' +export interface TransactionObject { + call + send + encodeABI + estimateGas +} export interface EventFilter { [key: string]: string } diff --git a/packages/api/template.handlebars b/packages/api/template.handlebars index c34b116ad..0366ca550 100644 --- a/packages/api/template.handlebars +++ b/packages/api/template.handlebars @@ -1,6 +1,7 @@ /* eslint-disable */ import { BigNumber } from 'bignumber.js' -import BaseContract, { EventFilter, EventOptions} from '../../baseContract' +import BaseContract, { EventOptions } from '../../baseContract' +import { TransactionObject } from 'web3/eth/types' {{#if events}} export enum {{contractName}}Events { diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index 52bb749cd..51a56c4e8 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -53,7 +53,10 @@ describe('generated contract', () => { const gasPrice = await web3.eth.getGasPrice() const gasEstimate = await vaultFactory // 2538415 .createVault(...vaultOptions) - .then(obj => obj.estimateGas(txOptions)) + .then(obj => { + console.log('OB J', obj) + return obj.estimateGas(txOptions) + }) const receipt = await vaultFactory .createVault(...vaultOptions) .then(obj => From be7752cfc00ac6226e68b26f051d97d25cda18d9 Mon Sep 17 00:00:00 2001 From: Federico Date: Thu, 27 Sep 2018 12:35:46 +0200 Subject: [PATCH 10/10] removed test file, minor refactor --- packages/api/prova.ts | 75 ----------------------------- packages/api/test/contracts.test.ts | 1 - packages/api/tsconfig.json | 1 - 3 files changed, 77 deletions(-) delete mode 100644 packages/api/prova.ts diff --git a/packages/api/prova.ts b/packages/api/prova.ts deleted file mode 100644 index 59542d06c..000000000 --- a/packages/api/prova.ts +++ /dev/null @@ -1,75 +0,0 @@ -import Web3 = require('web3') -import { - VaultFactory, - VaultFactoryEvents -} from './src/contracts/models/vault_factory' - -// const getData = async () => { -// const web3 = new Web3( -// new Web3.providers.WebsocketProvider('ws://localhost:8545') -// ) -// console.log('here') -// const accounts = await web3.eth.getAccounts() -// const vaultFactory = await VaultFactory.createAndValidate( -// web3, -// '0x7ce6e371085cb611fb46d5065397223ef2f952ff' -// ) -// const filterOptions: any = { -// fromBlock: 0, -// toBlock: 'latest' -// } -// const filterCallback = (err, event) => -// err ? console.error(err) : console.log(event) -// const events = await vaultFactory.allEvents(filterOptions, filterCallback) -// // --------------------- -// const vaultName = Math.random() -// .toString(36) -// .substring(2, 7) -// const txOptions = { -// from: accounts[0] -// } -// const gasPrice = await web3.eth.getGasPrice() -// const gasEstimate = await vaultFactory -// .createVault(vaultName, 'ASD') -// .then(obj => obj.estimateGas(txOptions)) -// const receipt = await vaultFactory -// .createVault(vaultName, 'ASD') -// .then(obj => obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 })) -// } -const getData = async () => { - const web3 = new Web3( - new Web3.providers.WebsocketProvider('ws://localhost:8545') - ) - console.log('here') - const accounts = await web3.eth.getAccounts() - const vaultFactory = await VaultFactory.createAndValidate( - web3, - '0x7ce6e371085cb611fb46d5065397223ef2f952ff' - ) - const filterOptions: any = { - fromBlock: 0, - toBlock: 'latest' - } - const filterCallback = (err, event) => - err ? console.error(err) : console.log(event) - const events = await vaultFactory.VaultCreatedEvent(filterOptions, undefined) - events.on('data', function(event) { - console.log(event) // same results as the optional callback above - }) - // --------------------- - const vaultName = Math.random() - .toString(36) - .substring(2, 7) - const txOptions = { - from: accounts[0] - } - const gasPrice = await web3.eth.getGasPrice() - const gasEstimate = await vaultFactory - .createVault(vaultName, 'ASD') - .then(obj => obj.estimateGas(txOptions)) - const receipt = await vaultFactory - .createVault(vaultName, 'ASD') - .then(obj => obj.send({ ...txOptions, gasPrice, gas: gasEstimate + 5000 })) -} - -getData() diff --git a/packages/api/test/contracts.test.ts b/packages/api/test/contracts.test.ts index 51a56c4e8..169f70e23 100644 --- a/packages/api/test/contracts.test.ts +++ b/packages/api/test/contracts.test.ts @@ -54,7 +54,6 @@ describe('generated contract', () => { const gasEstimate = await vaultFactory // 2538415 .createVault(...vaultOptions) .then(obj => { - console.log('OB J', obj) return obj.estimateGas(txOptions) }) const receipt = await vaultFactory diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index d9e49aace..9023efc9d 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -10,6 +10,5 @@ "declaration": true, "sourceMap": true, "pretty": true - // "typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"], } }