diff options
Diffstat (limited to 'src/ts')
-rw-r--r-- | src/ts/0x.js.ts | 134 | ||||
-rw-r--r-- | src/ts/contract_wrappers/contract_wrapper.ts | 48 | ||||
-rw-r--r-- | src/ts/contract_wrappers/exchange_wrapper.ts | 37 | ||||
-rw-r--r-- | src/ts/globals.d.ts | 63 | ||||
-rw-r--r-- | src/ts/schemas/ec_signature_schema.ts | 20 | ||||
-rw-r--r-- | src/ts/types.ts | 36 | ||||
-rw-r--r-- | src/ts/utils/assert.ts | 47 | ||||
-rw-r--r-- | src/ts/utils/constants.ts | 3 | ||||
-rw-r--r-- | src/ts/utils/schema_validator.ts | 14 | ||||
-rw-r--r-- | src/ts/utils/utils.ts | 18 | ||||
-rw-r--r-- | src/ts/web3_wrapper.ts | 69 |
11 files changed, 0 insertions, 489 deletions
diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts deleted file mode 100644 index 1ebafc604..000000000 --- a/src/ts/0x.js.ts +++ /dev/null @@ -1,134 +0,0 @@ -import * as _ from 'lodash'; -import * as BigNumber from 'bignumber.js'; -import * as ethUtil from 'ethereumjs-util'; -import contract = require('truffle-contract'); -import * as Web3 from 'web3'; -import * as ethABI from 'ethereumjs-abi'; -import {Web3Wrapper} from './web3_wrapper'; -import {constants} from './utils/constants'; -import {utils} from './utils/utils'; -import {assert} from './utils/assert'; -import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; -import {ECSignatureSchema} from './schemas/ec_signature_schema'; -import {SolidityTypes, ECSignature} from './types'; - -const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; - -export class ZeroEx { - public web3Wrapper: Web3Wrapper; - public exchange: ExchangeWrapper; - /** - * Computes the orderHash given the order parameters and returns it as a hex encoded string. - */ - public static getOrderHashHex(exchangeContractAddr: string, makerAddr: string, takerAddr: string, - tokenMAddress: string, tokenTAddress: string, feeRecipient: string, - valueM: BigNumber.BigNumber, valueT: BigNumber.BigNumber, - makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber, - expiration: BigNumber.BigNumber, salt: BigNumber.BigNumber): string { - takerAddr = _.isEmpty(takerAddr) ? constants.NULL_ADDRESS : takerAddr ; - assert.isETHAddressHex('exchangeContractAddr', exchangeContractAddr); - assert.isETHAddressHex('makerAddr', makerAddr); - assert.isETHAddressHex('takerAddr', takerAddr); - assert.isETHAddressHex('tokenMAddress', tokenMAddress); - assert.isETHAddressHex('tokenTAddress', tokenTAddress); - assert.isETHAddressHex('feeRecipient', feeRecipient); - assert.isBigNumber('valueM', valueM); - assert.isBigNumber('valueT', valueT); - assert.isBigNumber('makerFee', makerFee); - assert.isBigNumber('takerFee', takerFee); - assert.isBigNumber('expiration', expiration); - assert.isBigNumber('salt', salt); - - const orderParts = [ - {value: exchangeContractAddr, type: SolidityTypes.address}, - {value: makerAddr, type: SolidityTypes.address}, - {value: takerAddr, type: SolidityTypes.address}, - {value: tokenMAddress, type: SolidityTypes.address}, - {value: tokenTAddress, type: SolidityTypes.address}, - {value: feeRecipient, type: SolidityTypes.address}, - {value: utils.bigNumberToBN(valueM), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(valueT), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(makerFee), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(takerFee), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(expiration), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(salt), type: SolidityTypes.uint256}, - ]; - const types = _.map(orderParts, o => o.type); - const values = _.map(orderParts, o => o.value); - const hashBuff = ethABI.soliditySHA3(types, values); - const hashHex = ethUtil.bufferToHex(hashBuff); - return hashHex; - } - /** - * Verifies that the elliptic curve signature `signature` was generated - * by signing `data` with the private key corresponding to the `signerAddressHex` address. - */ - public static isValidSignature(dataHex: string, signature: ECSignature, signerAddressHex: string): boolean { - assert.isHexString('dataHex', dataHex); - assert.doesConformToSchema('signature', signature, ECSignatureSchema); - assert.isETHAddressHex('signerAddressHex', signerAddressHex); - - const dataBuff = ethUtil.toBuffer(dataHex); - const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff); - try { - const pubKey = ethUtil.ecrecover( - msgHashBuff, - signature.v, - ethUtil.toBuffer(signature.r), - ethUtil.toBuffer(signature.s)); - const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey)); - return retrievedAddress === signerAddressHex; - } catch (err) { - return false; - } - } - /** - * Generates pseudo-random 256 bit salt. - * The salt is used to ensure that the 0x order generated has a unique orderHash that does - * not collide with any other outstanding orders. - */ - public static generatePseudoRandomSalt(): BigNumber.BigNumber { - // BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places. - // Source: https://mikemcl.github.io/bignumber.js/#random - const randomNumber = BigNumber.random(MAX_DIGITS_IN_UNSIGNED_256_INT); - const factor = new BigNumber(10).pow(MAX_DIGITS_IN_UNSIGNED_256_INT - 1); - const salt = randomNumber.times(factor).round(); - return salt; - } - /** Checks if order hash is valid */ - public static isValidOrderHash(orderHash: string): boolean { - assert.isString('orderHash', orderHash); - const isValid = /^0x[0-9A-F]{64}$/i.test(orderHash); - return isValid; - } - /* - * 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. - */ - public static toUnitAmount(amount: BigNumber.BigNumber, decimals: number): BigNumber.BigNumber { - assert.isBigNumber('amount', amount); - assert.isNumber('decimals', decimals); - - 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 - */ - public static toBaseUnitAmount(amount: BigNumber.BigNumber, decimals: number): BigNumber.BigNumber { - assert.isBigNumber('amount', amount); - assert.isNumber('decimals', decimals); - - const unit = new BigNumber(10).pow(decimals); - const baseUnitAmount = amount.times(unit); - return baseUnitAmount; - } - constructor(web3: Web3) { - this.web3Wrapper = new Web3Wrapper(web3); - this.exchange = new ExchangeWrapper(this.web3Wrapper); - } -} diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts deleted file mode 100644 index 9f4cd8039..000000000 --- a/src/ts/contract_wrappers/contract_wrapper.ts +++ /dev/null @@ -1,48 +0,0 @@ -import * as _ from 'lodash'; -import contract = require('truffle-contract'); -import {Web3Wrapper} from '../web3_wrapper'; -import {ZeroExError} from '../types'; -import {utils} from '../utils/utils'; - -export class ContractWrapper { - public web3Wrapper: Web3Wrapper; - constructor(web3Wrapper: Web3Wrapper) { - this.web3Wrapper = web3Wrapper; - } - protected async instantiateContractIfExistsAsync(artifact: Artifact, address?: string): Promise<ContractInstance> { - const c = await contract(artifact); - const providerObj = this.web3Wrapper.getCurrentProvider(); - c.setProvider(providerObj); - - const networkIdIfExists = await this.web3Wrapper.getNetworkIdIfExistsAsync(); - const artifactNetworkConfigs = _.isUndefined(networkIdIfExists) ? - undefined : - artifact.networks[networkIdIfExists]; - let contractAddress; - if (!_.isUndefined(address)) { - contractAddress = address; - } else if (!_.isUndefined(artifactNetworkConfigs)) { - contractAddress = artifactNetworkConfigs.address; - } - - if (!_.isUndefined(contractAddress)) { - const doesContractExist = await this.web3Wrapper.doesContractExistAtAddressAsync(contractAddress); - if (!doesContractExist) { - throw new Error(ZeroExError.CONTRACT_DOES_NOT_EXIST); - } - } - - try { - const contractInstance = _.isUndefined(address) ? await c.deployed() : await c.at(address); - return contractInstance; - } catch (err) { - const errMsg = `${err}`; - if (_.includes(errMsg, 'not been deployed to detected network')) { - throw new Error(ZeroExError.CONTRACT_DOES_NOT_EXIST); - } else { - utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`); - throw new Error(ZeroExError.UNHANDLED_ERROR); - } - } - } -} diff --git a/src/ts/contract_wrappers/exchange_wrapper.ts b/src/ts/contract_wrappers/exchange_wrapper.ts deleted file mode 100644 index 38043dd55..000000000 --- a/src/ts/contract_wrappers/exchange_wrapper.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as _ from 'lodash'; -import {Web3Wrapper} from '../web3_wrapper'; -import {ECSignature, ZeroExError, ExchangeContract} from '../types'; -import {assert} from '../utils/assert'; -import {ContractWrapper} from './contract_wrapper'; -import * as ExchangeArtifacts from '../../artifacts/Exchange.json'; -import {ECSignatureSchema} from '../schemas/ec_signature_schema'; - -export class ExchangeWrapper extends ContractWrapper { - constructor(web3Wrapper: Web3Wrapper) { - super(web3Wrapper); - } - public async isValidSignatureAsync(dataHex: string, ecSignature: ECSignature, - signerAddressHex: string): Promise<boolean> { - assert.isHexString('dataHex', dataHex); - assert.doesConformToSchema('ecSignature', ecSignature, ECSignatureSchema); - assert.isETHAddressHex('signerAddressHex', signerAddressHex); - - const senderAddressIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); - assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); - - const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); - const exchangeInstance = contractInstance as ExchangeContract; - - const isValidSignature = await exchangeInstance.isValidSignature.call( - signerAddressHex, - dataHex, - ecSignature.v, - ecSignature.r, - ecSignature.s, - { - from: senderAddressIfExists, - }, - ); - return isValidSignature; - } -} diff --git a/src/ts/globals.d.ts b/src/ts/globals.d.ts deleted file mode 100644 index dee957f2f..000000000 --- a/src/ts/globals.d.ts +++ /dev/null @@ -1,63 +0,0 @@ -declare module 'chai-bignumber'; -declare module 'bn.js'; -declare module 'request-promise-native'; -declare module 'web3-provider-engine'; -declare module 'web3-provider-engine/subproviders/rpc'; - -declare interface Schema { - id: string; -} - -// HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion -// interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise -// disallow `namespace`, we disable tslint for the following. -/* tslint:disable */ -declare namespace Chai { - interface Assertion { - bignumber: Assertion; - eventually: Assertion; - } -} -/* tslint:enable */ - -declare module '*.json' { - const json: any; - /* tslint:disable */ - export default json; - /* tslint:enable */ -} - -declare module 'ethereumjs-util' { - const toBuffer: (dataHex: string) => Buffer; - const hashPersonalMessage: (msg: Buffer) => Buffer; - const bufferToHex: (buff: Buffer) => string; - const ecrecover: (msgHashBuff: Buffer, v: number, r: Buffer, s: Buffer) => string; - const pubToAddress: (pubKey: string) => Buffer; - const isValidAddress: (address: string) => boolean; - const bufferToInt: (buffer: Buffer) => number; -} - -// truffle-contract declarations -declare interface ContractInstance {} -declare interface ContractFactory { - setProvider: (providerObj: any) => void; - deployed: () => ContractInstance; - at: (address: string) => ContractInstance; -} -declare interface Artifact { - networks: {[networkId: number]: any}; -} -declare function contract(artifacts: Artifact): ContractFactory; -declare module 'truffle-contract' { - export = contract; -} - -// es6-promisify declarations -declare function promisify(original: any, settings?: any): ((...arg: any[]) => Promise<any>); -declare module 'es6-promisify' { - export = promisify; -} - -declare module 'ethereumjs-abi' { - const soliditySHA3: (argTypes: string[], args: any[]) => Buffer; -} diff --git a/src/ts/schemas/ec_signature_schema.ts b/src/ts/schemas/ec_signature_schema.ts deleted file mode 100644 index 94e58e53c..000000000 --- a/src/ts/schemas/ec_signature_schema.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const ECSignatureParameter = { - id: '/ECSignatureParameter', - type: 'string', - pattern: '^0[xX][0-9A-Fa-f]{64}$', -}; - -export const ECSignatureSchema = { - id: '/ECSignature', - properties: { - v: { - type: 'number', - minimum: 27, - maximum: 28, - }, - r: {$ref: '/ECSignatureParameter'}, - s: {$ref: '/ECSignatureParameter'}, - }, - required: ['v', 'r', 's'], - type: 'object', -}; diff --git a/src/ts/types.ts b/src/ts/types.ts deleted file mode 100644 index 4da03a4d3..000000000 --- a/src/ts/types.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as _ from 'lodash'; - -// Utility function to create a K:V from a list of strings -// Adapted from: https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html -function strEnum(values: string[]): {[key: string]: string} { - return _.reduce(values, (result, key) => { - result[key] = key; - return result; - }, Object.create(null)); -} - -export const ZeroExError = strEnum([ - 'CONTRACT_DOES_NOT_EXIST', - 'UNHANDLED_ERROR', - 'USER_HAS_NO_ASSOCIATED_ADDRESSES', -]); -export type ZeroExError = keyof typeof ZeroExError; - -/** - * Elliptic Curve signature - */ -export interface ECSignature { - v: number; - r: string; - s: string; -} - -export interface ExchangeContract { - isValidSignature: any; -} - -export const SolidityTypes = strEnum([ - 'address', - 'uint256', -]); -export type SolidityTypes = keyof typeof SolidityTypes; diff --git a/src/ts/utils/assert.ts b/src/ts/utils/assert.ts deleted file mode 100644 index 1baf572d1..000000000 --- a/src/ts/utils/assert.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as _ from 'lodash'; -import * as BigNumber from 'bignumber.js'; -import * as Web3 from 'web3'; -import {SchemaValidator} from './schema_validator'; - -const HEX_REGEX = /^0x[0-9A-F]*$/i; - -export const assert = { - isBigNumber(variableName: string, value: BigNumber.BigNumber): void { - const isBigNumber = _.isObject(value) && value.isBigNumber; - this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value)); - }, - isUndefined(value: any, variableName?: string): void { - this.assert(_.isUndefined(value), this.typeAssertionMessage(variableName, 'undefined', value)); - }, - isString(variableName: string, value: string): void { - this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value)); - }, - isHexString(variableName: string, value: string): void { - this.assert(_.isString(value) && HEX_REGEX.test(value), - this.typeAssertionMessage(variableName, 'HexString', value)); - }, - isETHAddressHex(variableName: string, value: string): void { - const web3 = new Web3(); - this.assert(web3.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value)); - }, - isNumber(variableName: string, value: number): void { - this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value)); - }, - doesConformToSchema(variableName: string, value: object, schema: Schema): void { - const schemaValidator = new SchemaValidator(); - const validationResult = schemaValidator.validate(value, schema); - const hasValidationErrors = validationResult.errors.length > 0; - const msg = `Expected ${variableName} to conform to schema ${schema.id} -Encountered: ${JSON.stringify(value, null, '\t')} -Validation errors: ${validationResult.errors.join(', ')}`; - this.assert(!hasValidationErrors, msg); - }, - assert(condition: boolean, message: string): void { - if (!condition) { - throw new Error(message); - } - }, - typeAssertionMessage(variableName: string, type: string, value: any): string { - return `Expected ${variableName} to be of type ${type}, encountered: ${value}`; - }, -}; diff --git a/src/ts/utils/constants.ts b/src/ts/utils/constants.ts deleted file mode 100644 index ec2fe744a..000000000 --- a/src/ts/utils/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const constants = { - NULL_ADDRESS: '0x0000000000000000000000000000000000000000', -}; diff --git a/src/ts/utils/schema_validator.ts b/src/ts/utils/schema_validator.ts deleted file mode 100644 index bd2f97d2b..000000000 --- a/src/ts/utils/schema_validator.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {Validator, ValidatorResult} from 'jsonschema'; -import {ECSignatureSchema, ECSignatureParameter} from '../schemas/ec_signature_schema'; - -export class SchemaValidator { - private validator: Validator; - constructor() { - this.validator = new Validator(); - this.validator.addSchema(ECSignatureParameter, ECSignatureParameter.id); - this.validator.addSchema(ECSignatureSchema, ECSignatureSchema.id); - } - public validate(instance: object, schema: Schema): ValidatorResult { - return this.validator.validate(instance, schema); - } -} diff --git a/src/ts/utils/utils.ts b/src/ts/utils/utils.ts deleted file mode 100644 index b514b702d..000000000 --- a/src/ts/utils/utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as BN from 'bn.js'; - -export const utils = { - /** - * Converts BigNumber instance to BN - * The only reason we convert to BN is to remain compatible with `ethABI. soliditySHA3` that - * expects values of Solidity type `uint` to be passed as type `BN`. - * We do not use BN anywhere else in the codebase. - */ - bigNumberToBN(value: BigNumber.BigNumber) { - return new BN(value.toString(), 10); - }, - consoleLog(message: string): void { - /* tslint:disable */ - console.log(message); - /* tslint:enable */ - }, -}; diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts deleted file mode 100644 index 3b460e4da..000000000 --- a/src/ts/web3_wrapper.ts +++ /dev/null @@ -1,69 +0,0 @@ -import * as _ from 'lodash'; -import * as Web3 from 'web3'; -import * as BigNumber from 'bignumber.js'; -import promisify = require('es6-promisify'); - -export class Web3Wrapper { - private web3: Web3; - constructor(web3: Web3) { - this.web3 = new Web3(); - this.web3.setProvider(web3.currentProvider); - } - public isAddress(address: string): boolean { - return this.web3.isAddress(address); - } - public async getSenderAddressIfExistsAsync(): Promise<string|undefined> { - const defaultAccount = this.web3.eth.defaultAccount; - if (!_.isUndefined(defaultAccount)) { - return defaultAccount; - } - const firstAccount = await this.getFirstAddressIfExistsAsync(); - return firstAccount; - } - public async getFirstAddressIfExistsAsync(): Promise<string|undefined> { - const addresses = await promisify(this.web3.eth.getAccounts)(); - if (_.isEmpty(addresses)) { - return undefined; - } - return (addresses as string[])[0]; - } - public async getNodeVersionAsync(): Promise<string> { - const nodeVersion = await promisify(this.web3.version.getNode)(); - return nodeVersion; - } - public getCurrentProvider(): Web3.Provider { - return this.web3.currentProvider; - } - public async getNetworkIdIfExistsAsync(): Promise<number|undefined> { - try { - const networkId = await this.getNetworkAsync(); - return Number(networkId); - } catch (err) { - return undefined; - } - } - public async getBalanceInEthAsync(owner: string): Promise<BigNumber.BigNumber> { - const balanceInWei = await promisify(this.web3.eth.getBalance)(owner); - const balanceEth = this.web3.fromWei(balanceInWei, 'ether'); - return balanceEth; - } - public async doesContractExistAtAddressAsync(address: string): Promise<boolean> { - const code = await promisify(this.web3.eth.getCode)(address); - // Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients - const zeroHexAddressRegex = /^0x0\{0,40\}$/i; - const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); - return didFindCode; - } - public async signTransactionAsync(address: string, message: string): Promise<string> { - const signData = await promisify(this.web3.eth.sign)(address, message); - return signData; - } - public async getBlockTimestampAsync(blockHash: string): Promise<number> { - const {timestamp} = await promisify(this.web3.eth.getBlock)(blockHash); - return timestamp; - } - private async getNetworkAsync(): Promise<number> { - const networkId = await promisify(this.web3.version.getNetwork)(); - return networkId; - } -} |