aboutsummaryrefslogtreecommitdiffstats
path: root/src/0x.js.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/0x.js.ts')
-rw-r--r--src/0x.js.ts64
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;
+ }
}