aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2019-02-02 08:11:15 +0800
committerAmir Bandeali <abandeali1@gmail.com>2019-02-06 01:23:09 +0800
commitc7c4cb9bc6824f12adf352253464c76f177b4914 (patch)
tree5746d4ec6322bb4fa0654f45f3f88c9575ce1e2e
parent1ada6796631ad4e281423407f6eb2602a16f119e (diff)
downloaddexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.tar
dexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.tar.gz
dexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.tar.bz2
dexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.tar.lz
dexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.tar.xz
dexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.tar.zst
dexon-0x-contracts-c7c4cb9bc6824f12adf352253464c76f177b4914.zip
Add transaction hash utils
-rw-r--r--packages/order-utils/src/eip712_utils.ts9
-rw-r--r--packages/order-utils/src/index.ts2
-rw-r--r--packages/order-utils/src/transaction_hash.ts46
-rw-r--r--packages/order-utils/test/transaction_hash_test.ts56
4 files changed, 108 insertions, 5 deletions
diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts
index 646d9e301..4b37dba41 100644
--- a/packages/order-utils/src/eip712_utils.ts
+++ b/packages/order-utils/src/eip712_utils.ts
@@ -11,16 +11,16 @@ export const eip712Utils = {
* @param primaryType The primary type found in message
* @param types The additional types for the data in message
* @param message The contents of the message
- * @param exchangeAddress The address of the exchange contract
+ * @param verifyingContractAddress The address of the verifying contract
* @return A typed data object
*/
createTypedData: (
primaryType: string,
types: EIP712Types,
message: EIP712Object,
- exchangeAddress: string,
+ verifyingContractAddress: string,
): EIP712TypedData => {
- assert.isETHAddressHex('exchangeAddress', exchangeAddress);
+ assert.isETHAddressHex('verifyingContractAddress', verifyingContractAddress);
assert.isString('primaryType', primaryType);
const typedData = {
types: {
@@ -30,7 +30,7 @@ export const eip712Utils = {
domain: {
name: constants.EIP712_DOMAIN_NAME,
version: constants.EIP712_DOMAIN_VERSION,
- verifyingContract: exchangeAddress,
+ verifyingContract: verifyingContractAddress,
},
message,
primaryType,
@@ -60,7 +60,6 @@ export const eip712Utils = {
* Creates an ExecuteTransaction EIP712TypedData object for use with signTypedData and
* 0x Exchange executeTransaction.
* @param ZeroExTransaction the 0x transaction
- * @param exchangeAddress The address of the exchange contract
* @return A typed data object
*/
createZeroExTransactionTypedData: (zeroExTransaction: ZeroExTransaction): EIP712TypedData => {
diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts
index 2150a02e4..26cbf9665 100644
--- a/packages/order-utils/src/index.ts
+++ b/packages/order-utils/src/index.ts
@@ -3,6 +3,7 @@ export { signatureUtils } from './signature_utils';
export { generatePseudoRandomSalt } from './salt';
export { assetDataUtils } from './asset_data_utils';
export { marketUtils } from './market_utils';
+export { transactionHashUtils } from './transaction_hash';
export { rateUtils } from './rate_utils';
export { sortingUtils } from './sorting_utils';
export { orderParsingUtils } from './parsing_utils';
@@ -51,6 +52,7 @@ export {
EIP712Object,
EIP712ObjectValue,
ZeroExTransaction,
+ SignedZeroExTransaction,
} from '@0x/types';
export {
OrderError,
diff --git a/packages/order-utils/src/transaction_hash.ts b/packages/order-utils/src/transaction_hash.ts
new file mode 100644
index 000000000..2b2345af7
--- /dev/null
+++ b/packages/order-utils/src/transaction_hash.ts
@@ -0,0 +1,46 @@
+import { schemas, SchemaValidator } from '@0x/json-schemas';
+import { SignedZeroExTransaction, ZeroExTransaction } from '@0x/types';
+import { signTypedDataUtils } from '@0x/utils';
+import * as _ from 'lodash';
+
+import { assert } from './assert';
+import { eip712Utils } from './eip712_utils';
+
+export const transactionHashUtils = {
+ /**
+ * Checks if the supplied hex encoded 0x transaction hash is valid.
+ * Note: Valid means it has the expected format, not that a transaction with the transactionHash exists.
+ * Use this method when processing transactionHashes submitted as user input.
+ * @param transactionHash Hex encoded transactionHash.
+ * @return Whether the supplied transactionHash has the expected format.
+ */
+ isValidTransactionHash(transactionHash: string): boolean {
+ // Since this method can be called to check if any arbitrary string conforms to an transactionHash's
+ // format, we only assert that we were indeed passed a string.
+ assert.isString('transactionHash', transactionHash);
+ const schemaValidator = new SchemaValidator();
+ const isValid = schemaValidator.validate(transactionHash, schemas.orderHashSchema).valid;
+ return isValid;
+ },
+ /**
+ * Computes the transactionHash for a supplied 0x transaction.
+ * @param transaction An object that conforms to the ZeroExTransaction or SignedZeroExTransaction interface definitions.
+ * @return Hex encoded string transactionHash from hashing the supplied order.
+ */
+ getTransactionHashHex(transaction: ZeroExTransaction | SignedZeroExTransaction): string {
+ assert.doesConformToSchema('transaction', transaction, schemas.zeroExTransactionSchema, [schemas.hexSchema]);
+ const transactionHashBuff = transactionHashUtils.getTransactionHashBuffer(transaction);
+ const transactionHashHex = `0x${transactionHashBuff.toString('hex')}`;
+ return transactionHashHex;
+ },
+ /**
+ * Computes the transactionHash for a supplied 0x transaction.
+ * @param transaction An object that conforms to the ZeroExTransaction or SignedZeroExTransaction interface definitions.
+ * @return A Buffer containing the resulting transactionHash from hashing the supplied 0x transaction.
+ */
+ getTransactionHashBuffer(transaction: ZeroExTransaction | SignedZeroExTransaction): Buffer {
+ const typedData = eip712Utils.createZeroExTransactionTypedData(transaction);
+ const transactionHashBuff = signTypedDataUtils.generateTypedDataHash(typedData);
+ return transactionHashBuff;
+ },
+};
diff --git a/packages/order-utils/test/transaction_hash_test.ts b/packages/order-utils/test/transaction_hash_test.ts
new file mode 100644
index 000000000..0c371c7c2
--- /dev/null
+++ b/packages/order-utils/test/transaction_hash_test.ts
@@ -0,0 +1,56 @@
+import { ZeroExTransaction } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { transactionHashUtils } from '../src';
+
+import { constants } from '../src/constants';
+
+import { chaiSetup } from './utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe.only('0x transaction hashing', () => {
+ describe('#getTransactionHashHex', () => {
+ const expectedTransactionHash = '0x82c9bb2dcac4f868ec7a15c20ff6175cfc384c20ae6a872aa0342a840f108c2b';
+ const fakeVerifyingContractAddress = '0x5e72914535f202659083db3a02c984188fa26e9f';
+ const transaction: ZeroExTransaction = {
+ verifyingContractAddress: fakeVerifyingContractAddress,
+ signerAddress: constants.NULL_ADDRESS,
+ salt: new BigNumber(0),
+ data: constants.NULL_BYTES,
+ };
+ it('calculates the transaction hash', async () => {
+ const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
+ expect(transactionHash).to.be.equal(expectedTransactionHash);
+ });
+ it('calculates the transaction hash if amounts are strings', async () => {
+ // It's common for developers using javascript to provide the amounts
+ // as strings. Since we eventually toString() the BigNumber
+ // before encoding we should result in the same orderHash in this scenario
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ const transactionHash = transactionHashUtils.getTransactionHashHex({
+ ...transaction,
+ salt: '0',
+ } as any);
+ expect(transactionHash).to.be.equal(expectedTransactionHash);
+ });
+ });
+ describe('#isValidTransactionHash', () => {
+ it('returns false if the value is not a hex string', () => {
+ const isValid = transactionHashUtils.isValidTransactionHash('not a hex');
+ expect(isValid).to.be.false();
+ });
+ it('returns false if the length is wrong', () => {
+ const isValid = transactionHashUtils.isValidTransactionHash('0xdeadbeef');
+ expect(isValid).to.be.false();
+ });
+ it('returns true if order hash is correct', () => {
+ const orderHashLength = 65;
+ const isValid = transactionHashUtils.isValidTransactionHash(`0x${Array(orderHashLength).join('0')}`);
+ expect(isValid).to.be.true();
+ });
+ });
+});