diff options
Diffstat (limited to 'src/0x.js.ts')
-rw-r--r-- | src/0x.js.ts | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/src/0x.js.ts b/src/0x.js.ts index de082146f..aed7513a8 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -8,9 +8,11 @@ import {Web3Wrapper} from './web3_wrapper'; import {constants} from './utils/constants'; import {utils} from './utils/utils'; import {assert} from './utils/assert'; +import findVersions = require('find-versions'); +import compareVersions = require('compare-versions'); import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {ECSignatureSchema} from './schemas/ec_signature_schema'; -import {SolidityTypes, ECSignature} from './types'; +import {SolidityTypes, ECSignature, ZeroExError} from './types'; const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; @@ -131,4 +133,64 @@ export class ZeroEx { this.web3Wrapper = new Web3Wrapper(web3); this.exchange = new ExchangeWrapper(this.web3Wrapper); } + /** + * Signs an orderHash and returns it's elliptic curve signature + * This method currently supports TestRPC, Geth and Parity above and below V1.6.6 + */ + public async signOrderHashAsync(orderHashHex: string): Promise<ECSignature> { + assert.isHexString('orderHashHex', orderHashHex); + + let msgHashHex; + const nodeVersion = await this.web3Wrapper.getNodeVersionAsync(); + const isParityNode = utils.isParityNode(nodeVersion); + if (isParityNode) { + // Parity node adds the personalMessage prefix itself + msgHashHex = orderHashHex; + } else { + const orderHashBuff = ethUtil.toBuffer(orderHashHex); + const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff); + msgHashHex = ethUtil.bufferToHex(msgHashBuff); + } + + const makerAddressIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); + if (_.isUndefined(makerAddressIfExists)) { + throw new Error(ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); + } + + const signature = await this.web3Wrapper.signTransactionAsync(makerAddressIfExists, msgHashHex); + + let signatureData; + const [nodeVersionNumber] = findVersions(nodeVersion); + // Parity v1.6.6 and earlier returns the signatureData as vrs instead of rsv as Geth does + // Later versions return rsv but for the time being we still want to support version < 1.6.6 + // Date: May 23rd 2017 + const latestParityVersionWithVRS = '1.6.6'; + const isVersionBeforeParityFix = compareVersions(nodeVersionNumber, latestParityVersionWithVRS) <= 0; + if (isParityNode && isVersionBeforeParityFix) { + const signatureBuffer = ethUtil.toBuffer(signature); + let v = signatureBuffer[0]; + if (v < 27) { + v += 27; + } + signatureData = { + v, + r: signatureBuffer.slice(1, 33), + s: signatureBuffer.slice(33, 65), + }; + } else { + signatureData = ethUtil.fromRpcSig(signature); + } + + const {v, r, s} = signatureData; + const ecSignature: ECSignature = { + v, + r: ethUtil.bufferToHex(r), + s: ethUtil.bufferToHex(s), + }; + const isValidSignature = ZeroEx.isValidSignature(orderHashHex, ecSignature, makerAddressIfExists); + if (!isValidSignature) { + throw new Error(ZeroExError.INVALID_SIGNATURE); + } + return ecSignature; + } } |