From 69f5f5e94627458f4eb41f4150cfa3d140658d09 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 7 Feb 2018 20:26:13 +0100 Subject: Split Order into signedOrder and metadata --- packages/website/ts/components/fill_order.tsx | 146 +++++++++++---------- packages/website/ts/schemas/metadata_schema.ts | 10 ++ packages/website/ts/schemas/order_schema.ts | 37 +----- packages/website/ts/schemas/signed_order_schema.ts | 34 +++++ packages/website/ts/schemas/validator.ts | 4 + packages/website/ts/types.ts | 14 +- packages/website/ts/utils/utils.ts | 48 +++---- 7 files changed, 164 insertions(+), 129 deletions(-) create mode 100644 packages/website/ts/schemas/metadata_schema.ts create mode 100644 packages/website/ts/schemas/signed_order_schema.ts diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index ceb06c95a..ad3d6bf74 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -182,16 +182,16 @@ export class FillOrder extends React.Component { ); } private _renderVisualOrder() { - const takerTokenAddress = this.state.parsedOrder.takerTokenAddress; + const takerTokenAddress = this.state.parsedOrder.signedOrder.takerTokenAddress; const takerToken = this.props.tokenByAddress[takerTokenAddress]; - const orderTakerAmount = new BigNumber(this.state.parsedOrder.takerTokenAmount); - const orderMakerAmount = new BigNumber(this.state.parsedOrder.makerTokenAmount); + const orderTakerAmount = new BigNumber(this.state.parsedOrder.signedOrder.takerTokenAmount); + const orderMakerAmount = new BigNumber(this.state.parsedOrder.signedOrder.makerTokenAmount); const takerAssetToken = { amount: orderTakerAmount.minus(this.state.unavailableTakerAmount), symbol: takerToken.symbol, }; const fillToken = this.props.tokenByAddress[takerTokenAddress]; - const makerTokenAddress = this.state.parsedOrder.makerTokenAddress; + const makerTokenAddress = this.state.parsedOrder.signedOrder.makerTokenAddress; const makerToken = this.props.tokenByAddress[makerTokenAddress]; const makerAssetToken = { amount: orderMakerAmount.times(takerAssetToken.amount).div(orderTakerAmount), @@ -201,10 +201,10 @@ export class FillOrder extends React.Component { amount: this.props.orderFillAmount, symbol: takerToken.symbol, }; - const orderTaker = !_.isEmpty(this.state.parsedOrder.taker) - ? this.state.parsedOrder.taker + const orderTaker = !_.isEmpty(this.state.parsedOrder.signedOrder.taker) + ? this.state.parsedOrder.signedOrder.taker : this.props.userAddress; - const parsedOrderExpiration = new BigNumber(this.state.parsedOrder.expirationUnixTimestampSec); + const parsedOrderExpiration = new BigNumber(this.state.parsedOrder.signedOrder.expirationUnixTimestampSec); const exchangeRate = orderMakerAmount.div(orderTakerAmount); let orderReceiveAmount = 0; @@ -213,7 +213,8 @@ export class FillOrder extends React.Component { orderReceiveAmount = this._formatCurrencyAmount(orderReceiveAmountBigNumber, makerToken.decimals); } const isUserMaker = - !_.isUndefined(this.state.parsedOrder) && this.state.parsedOrder.maker === this.props.userAddress; + !_.isUndefined(this.state.parsedOrder) && + this.state.parsedOrder.signedOrder.maker === this.props.userAddress; const expiryDate = utils.convertToReadableDateTimeFromUnixTimestamp(parsedOrderExpiration); return (
@@ -224,10 +225,13 @@ export class FillOrder extends React.Component { Maker:
- +
- +
@@ -235,7 +239,7 @@ export class FillOrder extends React.Component {
{ return; } - const makerTokenIfExists = this.props.tokenByAddress[this.state.parsedOrder.makerTokenAddress]; - const takerTokenIfExists = this.props.tokenByAddress[this.state.parsedOrder.takerTokenAddress]; + const makerTokenIfExists = this.props.tokenByAddress[this.state.parsedOrder.signedOrder.makerTokenAddress]; + const takerTokenIfExists = this.props.tokenByAddress[this.state.parsedOrder.signedOrder.takerTokenAddress]; const tokensToTrack: Token[] = []; const isUnseenMakerToken = _.isUndefined(makerTokenIfExists); const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked; if (isUnseenMakerToken) { tokensToTrack.push({ - ...this.state.parsedOrder.makerToken, - address: this.state.parsedOrder.makerTokenAddress, + ...this.state.parsedOrder.metadata.makerToken, + address: this.state.parsedOrder.signedOrder.makerTokenAddress, iconUrl: undefined, isTracked: false, isRegistered: false, @@ -379,8 +383,8 @@ export class FillOrder extends React.Component { const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked; if (isUnseenTakerToken) { tokensToTrack.push({ - ...this.state.parsedOrder.takerToken, - address: this.state.parsedOrder.takerTokenAddress, + ...this.state.parsedOrder.metadata.takerToken, + address: this.state.parsedOrder.signedOrder.takerTokenAddress, iconUrl: undefined, isTracked: false, isRegistered: false, @@ -413,36 +417,38 @@ export class FillOrder extends React.Component { parsedOrder = order; const exchangeContractAddr = this.props.blockchain.getExchangeContractAddressIfExists(); - const makerAmount = new BigNumber(parsedOrder.makerTokenAmount); - const takerAmount = new BigNumber(parsedOrder.takerTokenAmount); - const expiration = new BigNumber(parsedOrder.expirationUnixTimestampSec); - const salt = new BigNumber(parsedOrder.salt); - const parsedMakerFee = new BigNumber(parsedOrder.makerFee); - const parsedTakerFee = new BigNumber(parsedOrder.takerFee); + const makerAmount = new BigNumber(parsedOrder.signedOrder.makerTokenAmount); + const takerAmount = new BigNumber(parsedOrder.signedOrder.takerTokenAmount); + const expiration = new BigNumber(parsedOrder.signedOrder.expirationUnixTimestampSec); + const salt = new BigNumber(parsedOrder.signedOrder.salt); + const parsedMakerFee = new BigNumber(parsedOrder.signedOrder.makerFee); + const parsedTakerFee = new BigNumber(parsedOrder.signedOrder.takerFee); const zeroExOrder: ZeroExOrder = { - exchangeContractAddress: parsedOrder.exchangeContractAddress, + exchangeContractAddress: parsedOrder.signedOrder.exchangeContractAddress, expirationUnixTimestampSec: expiration, - feeRecipient: parsedOrder.feeRecipient, - maker: parsedOrder.maker, + feeRecipient: parsedOrder.signedOrder.feeRecipient, + maker: parsedOrder.signedOrder.maker, makerFee: parsedMakerFee, - makerTokenAddress: parsedOrder.makerTokenAddress, + makerTokenAddress: parsedOrder.signedOrder.makerTokenAddress, makerTokenAmount: makerAmount, salt, - taker: _.isEmpty(parsedOrder.taker) ? constants.NULL_ADDRESS : parsedOrder.taker, + taker: _.isEmpty(parsedOrder.signedOrder.taker) + ? constants.NULL_ADDRESS + : parsedOrder.signedOrder.taker, takerFee: parsedTakerFee, - takerTokenAddress: parsedOrder.takerTokenAddress, + takerTokenAddress: parsedOrder.signedOrder.takerTokenAddress, takerTokenAmount: takerAmount, }; const orderHash = ZeroEx.getOrderHashHex(zeroExOrder); - const signature = parsedOrder.ecSignature; - const isValidSignature = ZeroEx.isValidSignature(signature.hash, signature, parsedOrder.maker); - if (this.props.networkId !== parsedOrder.networkId) { + const signature = parsedOrder.signedOrder.ecSignature; + const isValidSignature = ZeroEx.isValidSignature(signature.hash, signature, parsedOrder.signedOrder.maker); + if (this.props.networkId !== parsedOrder.metadata.networkId) { orderJSONErrMsg = `This order was made on another Ethereum network - (id: ${parsedOrder.networkId}). Connect to this network to fill.`; + (id: ${parsedOrder.metadata.networkId}). Connect to this network to fill.`; parsedOrder = undefined; - } else if (exchangeContractAddr !== parsedOrder.exchangeContractAddress) { + } else if (exchangeContractAddr !== parsedOrder.signedOrder.exchangeContractAddress) { orderJSONErrMsg = 'This order was made using a deprecated 0x Exchange contract.'; parsedOrder = undefined; } else if (orderHash !== signature.hash) { @@ -477,13 +483,13 @@ export class FillOrder extends React.Component { // Clear cache entry if user updates orderJSON to invalid entry this.props.dispatcher.updateUserSuppliedOrderCache(undefined); } else { - const orderHash = parsedOrder.ecSignature.hash; + const orderHash = parsedOrder.signedOrder.ecSignature.hash; unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash); const isMakerTokenAddressInRegistry = await this.props.blockchain.isAddressInTokenRegistryAsync( - parsedOrder.makerTokenAddress, + parsedOrder.signedOrder.makerTokenAddress, ); const isTakerTokenAddressInRegistry = await this.props.blockchain.isAddressInTokenRegistryAsync( - parsedOrder.takerTokenAddress, + parsedOrder.signedOrder.takerTokenAddress, ); this.setState({ isMakerTokenAddressInRegistry, @@ -529,18 +535,18 @@ export class FillOrder extends React.Component { } const signedOrder = this.props.blockchain.portalOrderToSignedOrder( - parsedOrder.maker, - parsedOrder.taker, - parsedOrder.makerTokenAddress, - parsedOrder.takerTokenAddress, - new BigNumber(parsedOrder.makerTokenAmount), - new BigNumber(parsedOrder.takerTokenAmount), - new BigNumber(parsedOrder.makerFee), - new BigNumber(parsedOrder.takerFee), - new BigNumber(this.state.parsedOrder.expirationUnixTimestampSec), - parsedOrder.feeRecipient, - parsedOrder.ecSignature, - new BigNumber(parsedOrder.salt), + parsedOrder.signedOrder.maker, + parsedOrder.signedOrder.taker, + parsedOrder.signedOrder.makerTokenAddress, + parsedOrder.signedOrder.takerTokenAddress, + new BigNumber(parsedOrder.signedOrder.makerTokenAmount), + new BigNumber(parsedOrder.signedOrder.takerTokenAmount), + new BigNumber(parsedOrder.signedOrder.makerFee), + new BigNumber(parsedOrder.signedOrder.takerFee), + new BigNumber(this.state.parsedOrder.signedOrder.expirationUnixTimestampSec), + parsedOrder.signedOrder.feeRecipient, + parsedOrder.signedOrder.ecSignature, + new BigNumber(parsedOrder.signedOrder.salt), ); if (_.isEmpty(globalErrMsg)) { try { @@ -550,7 +556,7 @@ export class FillOrder extends React.Component { this.props.userAddress, ); } catch (err) { - globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.taker); + globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.signedOrder.taker); } } if (!_.isEmpty(globalErrMsg)) { @@ -561,7 +567,7 @@ export class FillOrder extends React.Component { return; } const networkName = constants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${parsedOrder.takerToken.symbol}-${networkName}`; + const eventLabel = `${parsedOrder.metadata.takerToken.symbol}-${networkName}`; try { const orderFilledAmount: BigNumber = await this.props.blockchain.fillOrderAsync( signedOrder, @@ -571,7 +577,7 @@ export class FillOrder extends React.Component { category: 'Portal', action: 'Fill Order Success', label: eventLabel, - value: parsedOrder.takerTokenAmount, + value: parsedOrder.signedOrder.takerTokenAmount, }); // After fill completes, let's force fetch the token balances this.props.dispatcher.forceTokenStateRefetch(); @@ -590,7 +596,7 @@ export class FillOrder extends React.Component { category: 'Portal', action: 'Fill Order Failure', label: eventLabel, - value: parsedOrder.takerTokenAmount, + value: parsedOrder.signedOrder.takerTokenAmount, }); const errMsg = `${err}`; if (utils.didUserDenyWeb3Request(errMsg)) { @@ -617,7 +623,7 @@ export class FillOrder extends React.Component { }); const parsedOrder = this.state.parsedOrder; - const orderHash = parsedOrder.ecSignature.hash; + const orderHash = parsedOrder.signedOrder.ecSignature.hash; const takerAddress = this.props.userAddress; if (_.isUndefined(takerAddress)) { @@ -629,28 +635,28 @@ export class FillOrder extends React.Component { } let globalErrMsg = ''; - const takerTokenAmount = new BigNumber(parsedOrder.takerTokenAmount); + const takerTokenAmount = new BigNumber(parsedOrder.signedOrder.takerTokenAmount); const signedOrder = this.props.blockchain.portalOrderToSignedOrder( - parsedOrder.maker, - parsedOrder.taker, - parsedOrder.makerTokenAddress, - parsedOrder.takerTokenAddress, - new BigNumber(parsedOrder.makerTokenAmount), + parsedOrder.signedOrder.maker, + parsedOrder.signedOrder.taker, + parsedOrder.signedOrder.makerTokenAddress, + parsedOrder.signedOrder.takerTokenAddress, + new BigNumber(parsedOrder.signedOrder.makerTokenAmount), takerTokenAmount, - new BigNumber(parsedOrder.makerFee), - new BigNumber(parsedOrder.takerFee), - new BigNumber(this.state.parsedOrder.expirationUnixTimestampSec), - parsedOrder.feeRecipient, - parsedOrder.ecSignature, - new BigNumber(parsedOrder.salt), + new BigNumber(parsedOrder.signedOrder.makerFee), + new BigNumber(parsedOrder.signedOrder.takerFee), + new BigNumber(this.state.parsedOrder.signedOrder.expirationUnixTimestampSec), + parsedOrder.signedOrder.feeRecipient, + parsedOrder.signedOrder.ecSignature, + new BigNumber(parsedOrder.signedOrder.salt), ); const unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash); const availableTakerTokenAmount = takerTokenAmount.minus(unavailableTakerAmount); try { await this.props.blockchain.validateCancelOrderThrowIfInvalidAsync(signedOrder, availableTakerTokenAmount); } catch (err) { - globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.taker); + globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.signedOrder.taker); } if (!_.isEmpty(globalErrMsg)) { this.setState({ @@ -660,7 +666,7 @@ export class FillOrder extends React.Component { return; } const networkName = constants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${parsedOrder.makerToken.symbol}-${networkName}`; + const eventLabel = `${parsedOrder.metadata.makerToken.symbol}-${networkName}`; try { await this.props.blockchain.cancelOrderAsync(signedOrder, availableTakerTokenAmount); this.setState({ @@ -673,7 +679,7 @@ export class FillOrder extends React.Component { category: 'Portal', action: 'Cancel Order Success', label: eventLabel, - value: parsedOrder.makerTokenAmount, + value: parsedOrder.signedOrder.makerTokenAmount, }); return; } catch (err) { @@ -688,7 +694,7 @@ export class FillOrder extends React.Component { category: 'Portal', action: 'Cancel Order Failure', label: eventLabel, - value: parsedOrder.makerTokenAmount, + value: parsedOrder.signedOrder.makerTokenAmount, }); globalErrMsg = 'Failed to cancel order, please refresh and try again'; utils.consoleLog(`${err}`); diff --git a/packages/website/ts/schemas/metadata_schema.ts b/packages/website/ts/schemas/metadata_schema.ts new file mode 100644 index 000000000..272b23fbd --- /dev/null +++ b/packages/website/ts/schemas/metadata_schema.ts @@ -0,0 +1,10 @@ +export const orderMetadataSchema = { + id: '/OrderMetadata', + properties: { + makerToken: { $ref: '/Token' }, + takerToken: { $ref: '/Token' }, + networkId: { type: 'number' }, + }, + required: ['makerToken', 'takerToken', 'networkId'], + type: 'object', +}; diff --git a/packages/website/ts/schemas/order_schema.ts b/packages/website/ts/schemas/order_schema.ts index 6ddc9e445..0c5a6d425 100644 --- a/packages/website/ts/schemas/order_schema.ts +++ b/packages/website/ts/schemas/order_schema.ts @@ -1,40 +1,9 @@ export const orderSchema = { id: '/Order', properties: { - maker: { type: 'string' }, - taker: { type: 'string' }, - makerTokenAddress: { type: 'string' }, - takerTokenAddress: { type: 'string' }, - makerToken: { $ref: '/Token' }, - takerToken: { $ref: '/Token' }, - makerFee: { type: 'string' }, - takerFee: { type: 'string' }, - makerTokenAmount: { type: 'string' }, - takerTokenAmount: { type: 'string' }, - salt: { type: 'string' }, - ecSignature: { $ref: '/SignatureData' }, - expirationUnixTimestampSec: { type: 'string' }, - feeRecipient: { type: 'string' }, - exchangeContractAddress: { type: 'string' }, - networkId: { type: 'number' }, + signedOrder: { $ref: '/SignedOrder' }, + metadata: { $ref: '/OrderMetadata' }, }, - required: [ - 'maker', - 'taker', - 'makerTokenAddress', - 'takerTokenAddress', - 'makerToken', - 'takerToken', - 'makerFee', - 'takerFee', - 'makerTokenAmount', - 'takerTokenAmount', - 'salt', - 'ecSignature', - 'expirationUnixTimestampSec', - 'feeRecipient', - 'exchangeContractAddress', - 'networkId', - ], + required: ['signedOrder', 'metadata'], type: 'object', }; diff --git a/packages/website/ts/schemas/signed_order_schema.ts b/packages/website/ts/schemas/signed_order_schema.ts new file mode 100644 index 000000000..385008ab8 --- /dev/null +++ b/packages/website/ts/schemas/signed_order_schema.ts @@ -0,0 +1,34 @@ +export const signedOrderSchema = { + id: '/SignedOrder', + properties: { + maker: { type: 'string' }, + taker: { type: 'string' }, + makerTokenAddress: { type: 'string' }, + takerTokenAddress: { type: 'string' }, + makerFee: { type: 'string' }, + takerFee: { type: 'string' }, + makerTokenAmount: { type: 'string' }, + takerTokenAmount: { type: 'string' }, + salt: { type: 'string' }, + ecSignature: { $ref: '/SignatureData' }, + expirationUnixTimestampSec: { type: 'string' }, + feeRecipient: { type: 'string' }, + exchangeContractAddress: { type: 'string' }, + }, + required: [ + 'maker', + 'taker', + 'makerTokenAddress', + 'takerTokenAddress', + 'makerFee', + 'takerFee', + 'makerTokenAmount', + 'takerTokenAmount', + 'salt', + 'ecSignature', + 'expirationUnixTimestampSec', + 'feeRecipient', + 'exchangeContractAddress', + ], + type: 'object', +}; diff --git a/packages/website/ts/schemas/validator.ts b/packages/website/ts/schemas/validator.ts index e2ffc7b79..14061e2a3 100644 --- a/packages/website/ts/schemas/validator.ts +++ b/packages/website/ts/schemas/validator.ts @@ -1,6 +1,8 @@ import { Schema as JSONSchema, Validator } from 'jsonschema'; +import { orderMetadataSchema } from 'ts/schemas/metadata_schema'; import { orderSchema } from 'ts/schemas/order_schema'; import { signatureDataSchema } from 'ts/schemas/signature_data_schema'; +import { signedOrderSchema } from 'ts/schemas/signed_order_schema'; import { tokenSchema } from 'ts/schemas/token_schema'; export class SchemaValidator { @@ -9,6 +11,8 @@ export class SchemaValidator { this._validator = new Validator(); this._validator.addSchema(signatureDataSchema as JSONSchema, signatureDataSchema.id); this._validator.addSchema(tokenSchema as JSONSchema, tokenSchema.id); + this._validator.addSchema(orderMetadataSchema as JSONSchema, orderMetadataSchema.id); + this._validator.addSchema(signedOrderSchema as JSONSchema, signedOrderSchema.id); this._validator.addSchema(orderSchema as JSONSchema, orderSchema.id); } public validate(instance: object, schema: Schema) { diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 2526ca669..9281310d1 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -59,13 +59,11 @@ export interface OrderToken { decimals: number; } -export interface Order { +export interface SignedOrder { maker: string; taker: string; makerTokenAddress: string; takerTokenAddress: string; - makerToken: OrderToken; - takerToken: OrderToken; makerFee: string; takerFee: string; makerTokenAmount: string; @@ -75,7 +73,17 @@ export interface Order { salt: string; ecSignature: SignatureData; exchangeContractAddress: string; +} + +export interface OrderMetadata { networkId: number; + makerToken: OrderToken; + takerToken: OrderToken; +} + +export interface Order { + signedOrder: SignedOrder; + metadata: OrderMetadata; } export interface Fill { diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 2f1b2cce3..279b2c1b2 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -75,30 +75,34 @@ export const utils = { const makerToken = tokenByAddress[sideToAssetToken[Side.Deposit].address]; const takerToken = tokenByAddress[sideToAssetToken[Side.Receive].address]; const order = { - maker: orderMakerAddress, - taker: orderTakerAddress, - makerFee: makerFee.toString(), - takerFee: takerFee.toString(), - makerTokenAmount: sideToAssetToken[Side.Deposit].amount.toString(), - takerTokenAmount: sideToAssetToken[Side.Receive].amount.toString(), - makerTokenAddress: makerToken.address, - takerTokenAddress: takerToken.address, - makerToken: { - name: makerToken.name, - symbol: makerToken.symbol, - decimals: makerToken.decimals, + signedOrder: { + maker: orderMakerAddress, + taker: orderTakerAddress, + makerFee: makerFee.toString(), + takerFee: takerFee.toString(), + makerTokenAmount: sideToAssetToken[Side.Deposit].amount.toString(), + takerTokenAmount: sideToAssetToken[Side.Receive].amount.toString(), + makerTokenAddress: makerToken.address, + takerTokenAddress: takerToken.address, + expirationUnixTimestampSec: expirationUnixTimestampSec.toString(), + feeRecipient, + salt: orderSalt.toString(), + ecSignature, + exchangeContractAddress, }, - takerToken: { - name: takerToken.name, - symbol: takerToken.symbol, - decimals: takerToken.decimals, + metadata: { + networkId, + makerToken: { + name: makerToken.name, + symbol: makerToken.symbol, + decimals: makerToken.decimals, + }, + takerToken: { + name: takerToken.name, + symbol: takerToken.symbol, + decimals: takerToken.decimals, + }, }, - expirationUnixTimestampSec: expirationUnixTimestampSec.toString(), - feeRecipient, - salt: orderSalt.toString(), - ecSignature, - exchangeContractAddress, - networkId, }; return order; }, -- cgit