From 249bf0163d8ee71b7329fd58b72e554c0324279c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 3 Apr 2018 16:19:38 +0300 Subject: Move our contract templates to accept Provider instead of Web3Wrapper --- packages/web3-wrapper/CHANGELOG.json | 13 +++++ packages/web3-wrapper/coverage/.gitkeep | 0 packages/web3-wrapper/package.json | 16 ++++- packages/web3-wrapper/src/web3_wrapper.ts | 78 +++++++++++++++++-------- packages/web3-wrapper/test/utils/chai_setup.ts | 13 +++++ packages/web3-wrapper/test/web3_wrapper_test.ts | 39 +++++++++++++ packages/web3-wrapper/tsconfig.json | 2 +- 7 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 packages/web3-wrapper/coverage/.gitkeep create mode 100644 packages/web3-wrapper/test/utils/chai_setup.ts create mode 100644 packages/web3-wrapper/test/web3_wrapper_test.ts (limited to 'packages/web3-wrapper') diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json index bdf09f81e..14e45dacb 100644 --- a/packages/web3-wrapper/CHANGELOG.json +++ b/packages/web3-wrapper/CHANGELOG.json @@ -1,4 +1,17 @@ [ + { + "version": "0.6.0", + "changes": [ + { + "note": "Make `isAddress` and `toWei` static", + "pr": 501 + }, + { + "note": "Add static methods `toUnitAmount` and `toBaseUnitAmount`", + "pr": 501 + } + ] + }, { "version": "0.5.0", "changes": [ diff --git a/packages/web3-wrapper/coverage/.gitkeep b/packages/web3-wrapper/coverage/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 20fa39b07..910d4725e 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -2,13 +2,18 @@ "name": "@0xproject/web3-wrapper", "version": "0.5.0", "description": "Wraps around web3 and gives a nicer interface", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "lib/src/index.js", + "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib scripts", "lint": "tslint --project . 'src/**/*.ts'", + "test": "run-s clean build run_mocha", + "test:circleci": "yarn test:coverage", + "run_mocha": "mocha lib/test/**/*_test.js --bail --exit", + "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", + "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", "docs:stage": "yarn build && node ./scripts/stage_docs.js", "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES", @@ -41,6 +46,13 @@ "copyfiles": "^1.2.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", + "chai": "^4.0.1", + "mocha": "^4.0.1", + "nyc": "^11.0.1", + "ganache-core": "0xProject/ganache-core", + "chai-as-promised": "^7.1.0", + "chai-bignumber": "^2.0.1", + "dirty-chai": "^2.0.1", "tslint": "5.8.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index d75f39ed5..5e6ff3239 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -7,12 +7,13 @@ import { JSONRPCRequestPayload, JSONRPCResponsePayload, LogEntry, + Provider, RawLogEntry, TransactionReceipt, TransactionReceiptWithDecodedLogs, TxData, } from '@0xproject/types'; -import { AbiDecoder, BigNumber, intervalUtils, promisify } from '@0xproject/utils'; +import { AbiDecoder, addressUtils, BigNumber, intervalUtils, promisify } from '@0xproject/utils'; import * as _ from 'lodash'; import * as Web3 from 'web3'; @@ -30,6 +31,54 @@ export class Web3Wrapper { private _web3: Web3; private _defaults: Partial; private _jsonRpcRequestId: number; + /** + * Check if an address is a valid Ethereum address + * @param address Address to check + * @returns Whether the address is a valid Ethereum address + */ + public static isAddress(address: string): boolean { + return addressUtils.isAddress(address); + } + /** + * A unit amount is defined as the amount of a token above the specified decimal places (integer part). + * E.g: If a currency has 18 decimal places, 1e18 or one quintillion of the currency is equivalent + * to 1 unit. + * @param amount The amount in baseUnits that you would like converted to units. + * @param decimals The number of decimal places the unit amount has. + * @return The amount in units. + */ + public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber { + const aUnit = new BigNumber(10).pow(decimals); + const unit = amount.div(aUnit); + return unit; + } + /** + * A baseUnit is defined as the smallest denomination of a token. An amount expressed in baseUnits + * is the amount expressed in the smallest denomination. + * E.g: 1 unit of a token with 18 decimal places is expressed in baseUnits as 1000000000000000000 + * @param amount The amount of units that you would like converted to baseUnits. + * @param decimals The number of decimal places the unit amount has. + * @return The amount in baseUnits. + */ + public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber { + const unit = new BigNumber(10).pow(decimals); + const baseUnitAmount = amount.times(unit); + const hasDecimals = baseUnitAmount.decimalPlaces() !== 0; + if (hasDecimals) { + throw new Error(`Invalid unit amount: ${amount.toString()} - Too many decimal places`); + } + return baseUnitAmount; + } + /** + * Convert an Ether amount from ETH to Wei + * @param ethAmount Amount of Ether to convert to wei + * @returns Amount in wei + */ + public static toWei(ethAmount: BigNumber): BigNumber { + const ETH_DECIMALS = 18; + const balanceWei = Web3Wrapper.toBaseUnitAmount(ethAmount, ETH_DECIMALS); + return balanceWei; + } /** * Instantiates a new Web3Wrapper. * @param provider The Web3 provider instance you would like the Web3Wrapper to use for interacting with @@ -37,7 +86,7 @@ export class Web3Wrapper { * @param defaults Override TxData defaults sent with RPC requests to the backing Ethereum node. * @return An instance of the Web3Wrapper class. */ - constructor(provider: Web3.Provider, defaults?: Partial) { + constructor(provider: Provider, defaults?: Partial) { if (_.isUndefined((provider as any).sendAsync)) { // Web3@1.0 provider doesn't support synchronous http requests, // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x` @@ -61,24 +110,16 @@ export class Web3Wrapper { * Retrieve the Web3 provider * @return Web3 provider instance */ - public getProvider(): Web3.Provider { + public getProvider(): Provider { return this._web3.currentProvider; } /** * Update the used Web3 provider * @param provider The new Web3 provider to be set */ - public setProvider(provider: Web3.Provider) { + public setProvider(provider: Provider) { this._web3.setProvider(provider); } - /** - * Check if an address is a valid Ethereum address - * @param address Address to check - * @returns Whether the address is a valid Ethereum address - */ - public isAddress(address: string): boolean { - return this._web3.isAddress(address); - } /** * Check whether an address is available through the backing provider. This can be * useful if you want to know whether a user can sign messages or transactions from @@ -96,7 +137,7 @@ export class Web3Wrapper { * @returns Ethereum node's version string */ public async getNodeVersionAsync(): Promise { - const nodeVersion = await promisify(this._web3.version.getNode)(); + const nodeVersion = await this._sendRawPayloadAsync({ method: 'web3_clientVersion' }); return nodeVersion; } /** @@ -104,7 +145,7 @@ export class Web3Wrapper { * @returns The network id */ public async getNetworkIdAsync(): Promise { - const networkIdStr = await promisify(this._web3.version.getNetwork)(); + const networkIdStr = await this._sendRawPayloadAsync({ method: 'net_version' }); const networkId = _.parseInt(networkIdStr); return networkId; } @@ -120,15 +161,6 @@ export class Web3Wrapper { } return transactionReceipt; } - /** - * Convert an Ether amount from ETH to Wei - * @param ethAmount Amount of Ether to convert to wei - * @returns Amount in wei - */ - public toWei(ethAmount: BigNumber): BigNumber { - const balanceWei = this._web3.toWei(ethAmount, 'ether'); - return balanceWei; - } /** * Retrieves an accounts Ether balance in wei * @param owner Account whose balance you wish to check diff --git a/packages/web3-wrapper/test/utils/chai_setup.ts b/packages/web3-wrapper/test/utils/chai_setup.ts new file mode 100644 index 000000000..078edd309 --- /dev/null +++ b/packages/web3-wrapper/test/utils/chai_setup.ts @@ -0,0 +1,13 @@ +import * as chai from 'chai'; +import chaiAsPromised = require('chai-as-promised'); +import ChaiBigNumber = require('chai-bignumber'); +import * as dirtyChai from 'dirty-chai'; + +export const chaiSetup = { + configure() { + chai.config.includeStack = true; + chai.use(ChaiBigNumber()); + chai.use(dirtyChai); + chai.use(chaiAsPromised); + }, +}; diff --git a/packages/web3-wrapper/test/web3_wrapper_test.ts b/packages/web3-wrapper/test/web3_wrapper_test.ts new file mode 100644 index 000000000..2bf3badaa --- /dev/null +++ b/packages/web3-wrapper/test/web3_wrapper_test.ts @@ -0,0 +1,39 @@ +import * as chai from 'chai'; +import * as Ganache from 'ganache-core'; +import 'mocha'; + +import { Web3Wrapper } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +chaiSetup.configure(); + +const { expect } = chai; + +describe('Web3Wrapper tests', () => { + const NETWORK_ID = 50; + const provider = Ganache.provider({ network_id: NETWORK_ID }); + const web3Wrapper = new Web3Wrapper(provider); + describe('#isAddress', () => { + it('correctly checks if a string is a valid ethereum address', () => { + expect(Web3Wrapper.isAddress('0x0')).to.be.false(); + expect(Web3Wrapper.isAddress('0xdeadbeef')).to.be.false(); + expect(Web3Wrapper.isAddress('42')).to.be.false(); + expect(Web3Wrapper.isAddress('weth.thetoken.eth')).to.be.false(); + expect(Web3Wrapper.isAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2')).to.be.true(); + expect(Web3Wrapper.isAddress('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')).to.be.true(); + }); + }); + describe('#getNodeVersionAsync', () => { + it('gets the node version', async () => { + const nodeVersion = await web3Wrapper.getNodeVersionAsync(); + const NODE_VERSION = 'EthereumJS TestRPC/v2.1.0/ethereum-js'; + expect(nodeVersion).to.be.equal(NODE_VERSION); + }); + }); + describe('#getNetworkIdAsync', () => { + it('gets the network id', async () => { + const networkId = await web3Wrapper.getNetworkIdAsync(); + expect(networkId).to.be.equal(NETWORK_ID); + }); + }); +}); diff --git a/packages/web3-wrapper/tsconfig.json b/packages/web3-wrapper/tsconfig.json index c56d255d5..8b4cd47a2 100644 --- a/packages/web3-wrapper/tsconfig.json +++ b/packages/web3-wrapper/tsconfig.json @@ -3,5 +3,5 @@ "compilerOptions": { "outDir": "lib" }, - "include": ["./src/**/*"] + "include": ["src/**/*", "test/**/*"] } -- cgit v1.2.3