diff options
Diffstat (limited to 'packages/order-utils/src')
-rw-r--r-- | packages/order-utils/src/constants.ts | 10 | ||||
-rw-r--r-- | packages/order-utils/src/eip712_utils.ts | 55 | ||||
-rw-r--r-- | packages/order-utils/src/index.ts | 12 | ||||
-rw-r--r-- | packages/order-utils/src/order_hash.ts | 17 | ||||
-rw-r--r-- | packages/order-utils/src/transaction_hash.ts | 46 |
5 files changed, 112 insertions, 28 deletions
diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index a9a687719..3c93575b3 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -68,9 +68,9 @@ export const constants = { SELECTOR_CHAR_LENGTH_WITH_PREFIX: 10, INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite ZERO_AMOUNT: new BigNumber(0), - EIP712_DOMAIN_NAME: '0x Protocol', - EIP712_DOMAIN_VERSION: '2', - EIP712_DOMAIN_SCHEMA: { + EXCHANGE_DOMAIN_NAME: '0x Protocol', + EXCHANGE_DOMAIN_VERSION: '2', + DEFAULT_DOMAIN_SCHEMA: { name: 'EIP712Domain', parameters: [ { name: 'name', type: 'string' }, @@ -78,7 +78,7 @@ export const constants = { { name: 'verifyingContract', type: 'address' }, ], }, - EIP712_ORDER_SCHEMA: { + EXCHANGE_ORDER_SCHEMA: { name: 'Order', parameters: [ { name: 'makerAddress', type: 'address' }, @@ -95,7 +95,7 @@ export const constants = { { name: 'takerAssetData', type: 'bytes' }, ], }, - EIP712_ZEROEX_TRANSACTION_SCHEMA: { + EXCHANGE_ZEROEX_TRANSACTION_SCHEMA: { name: 'ZeroExTransaction', parameters: [ { name: 'salt', type: 'uint256' }, diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts index 385fda989..313653c63 100644 --- a/packages/order-utils/src/eip712_utils.ts +++ b/packages/order-utils/src/eip712_utils.ts @@ -1,36 +1,49 @@ import { assert } from '@0x/assert'; import { schemas } from '@0x/json-schemas'; -import { EIP712Object, EIP712TypedData, EIP712Types, Order, ZeroExTransaction } from '@0x/types'; +import { + EIP712DomainWithDefaultSchema, + EIP712Object, + EIP712TypedData, + EIP712Types, + Order, + ZeroExTransaction, +} from '@0x/types'; import * as _ from 'lodash'; import { constants } from './constants'; +export const DEFAULT_DOMAIN_SCHEMA = constants.DEFAULT_DOMAIN_SCHEMA; +export const EXCHANGE_DOMAIN_NAME = constants.EXCHANGE_DOMAIN_NAME; +export const EXCHANGE_DOMAIN_VERSION = constants.EXCHANGE_DOMAIN_VERSION; +export const EXCHANGE_ORDER_SCHEMA = constants.EXCHANGE_ORDER_SCHEMA; +export const EXCHANGE_ZEROEX_TRANSACTION_SCHEMA = constants.EXCHANGE_ZEROEX_TRANSACTION_SCHEMA; + export const eip712Utils = { /** * Creates a EIP712TypedData object specific to the 0x protocol for use with signTypedData. * @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 domain Domain containing a name (optional), version (optional), and verifying contract address * @return A typed data object */ createTypedData: ( primaryType: string, types: EIP712Types, message: EIP712Object, - exchangeAddress: string, + domain: EIP712DomainWithDefaultSchema, ): EIP712TypedData => { - assert.isETHAddressHex('exchangeAddress', exchangeAddress); + assert.isETHAddressHex('verifyingContractAddress', domain.verifyingContractAddress); assert.isString('primaryType', primaryType); const typedData = { types: { - EIP712Domain: constants.EIP712_DOMAIN_SCHEMA.parameters, + EIP712Domain: DEFAULT_DOMAIN_SCHEMA.parameters, ...types, }, domain: { - name: constants.EIP712_DOMAIN_NAME, - version: constants.EIP712_DOMAIN_VERSION, - verifyingContract: exchangeAddress, + name: _.isUndefined(domain.name) ? EXCHANGE_DOMAIN_NAME : domain.name, + version: _.isUndefined(domain.version) ? EXCHANGE_DOMAIN_VERSION : domain.version, + verifyingContract: domain.verifyingContractAddress, }, message, primaryType, @@ -48,11 +61,14 @@ export const eip712Utils = { const normalizedOrder = _.mapValues(order, value => { return !_.isString(value) ? value.toString() : value; }); + const domain = { + verifyingContractAddress: order.exchangeAddress, + }; const typedData = eip712Utils.createTypedData( - constants.EIP712_ORDER_SCHEMA.name, - { Order: constants.EIP712_ORDER_SCHEMA.parameters }, + EXCHANGE_ORDER_SCHEMA.name, + { Order: EXCHANGE_ORDER_SCHEMA.parameters }, normalizedOrder, - order.exchangeAddress, + domain, ); return typedData; }, @@ -60,23 +76,22 @@ 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, - exchangeAddress: string, - ): EIP712TypedData => { - assert.isETHAddressHex('exchangeAddress', exchangeAddress); + createZeroExTransactionTypedData: (zeroExTransaction: ZeroExTransaction): EIP712TypedData => { + assert.isETHAddressHex('verifyingContractAddress', zeroExTransaction.verifyingContractAddress); assert.doesConformToSchema('zeroExTransaction', zeroExTransaction, schemas.zeroExTransactionSchema); const normalizedTransaction = _.mapValues(zeroExTransaction, value => { return !_.isString(value) ? value.toString() : value; }); + const domain = { + verifyingContractAddress: zeroExTransaction.verifyingContractAddress, + }; const typedData = eip712Utils.createTypedData( - constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.name, - { ZeroExTransaction: constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.parameters }, + EXCHANGE_ZEROEX_TRANSACTION_SCHEMA.name, + { ZeroExTransaction: EXCHANGE_ZEROEX_TRANSACTION_SCHEMA.parameters }, normalizedTransaction, - exchangeAddress, + domain, ); return typedData; }, diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 2150a02e4..436677efc 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'; @@ -18,7 +19,14 @@ export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store'; export { OrderFilledCancelledLazyStore } from './store/order_filled_cancelled_lazy_store'; -export { eip712Utils } from './eip712_utils'; +export { + eip712Utils, + DEFAULT_DOMAIN_SCHEMA, + EXCHANGE_DOMAIN_NAME, + EXCHANGE_DOMAIN_VERSION, + EXCHANGE_ORDER_SCHEMA, + EXCHANGE_ZEROEX_TRANSACTION_SCHEMA, +} from './eip712_utils'; export { Provider, @@ -50,7 +58,9 @@ export { EIP712Types, EIP712Object, EIP712ObjectValue, + EIP712DomainWithDefaultSchema, ZeroExTransaction, + SignedZeroExTransaction, } from '@0x/types'; export { OrderError, diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts index c8e9be71e..ce7e6d85f 100644 --- a/packages/order-utils/src/order_hash.ts +++ b/packages/order-utils/src/order_hash.ts @@ -4,6 +4,7 @@ import { signTypedDataUtils } from '@0x/utils'; import * as _ from 'lodash'; import { assert } from './assert'; +import { constants } from './constants'; import { eip712Utils } from './eip712_utils'; const INVALID_TAKER_FORMAT = 'instance.takerAddress is not of a type(s) string'; @@ -34,8 +35,9 @@ export const orderHashUtils = { assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); } catch (error) { if (_.includes(error.message, INVALID_TAKER_FORMAT)) { - const errMsg = - 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS'; + const errMsg = `Order taker must be of type string. If you want anyone to be able to fill an order - pass ${ + constants.NULL_ADDRESS + }`; throw new Error(errMsg); } throw error; @@ -51,6 +53,17 @@ export const orderHashUtils = { * @return A Buffer containing the resulting orderHash from hashing the supplied order */ getOrderHashBuffer(order: SignedOrder | Order): Buffer { + try { + assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); + } catch (error) { + if (_.includes(error.message, INVALID_TAKER_FORMAT)) { + const errMsg = `Order taker must be of type string. If you want anyone to be able to fill an order - pass ${ + constants.NULL_ADDRESS + }`; + throw new Error(errMsg); + } + throw error; + } const typedData = eip712Utils.createOrderTypedData(order); const orderHashBuff = signTypedDataUtils.generateTypedDataHash(typedData); return orderHashBuff; 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; + }, +}; |