Refactor/3.0/coordinator client (#2348)

* deduplicate migrateOnceAsync() test helper

* move and rename coordinator client to @0x/contracts-coordinator
This commit is contained in:
Xianny
2019-11-22 12:19:00 -08:00
committed by GitHub
parent f6d26392fb
commit 50d5b4fa37
30 changed files with 1604 additions and 1625 deletions

View File

@@ -64,7 +64,6 @@
"ethereum-types": "^2.2.0-beta.2",
"lodash": "^4.17.11",
"mocha": "^6.2.0",
"nock": "^10.0.6",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typedoc": "^0.15.0",
@@ -76,8 +75,7 @@
"@0x/contract-addresses": "^3.3.0-beta.4",
"@0x/contract-artifacts": "^2.3.0-beta.3",
"@0x/order-utils": "^8.5.0-beta.3",
"ethers": "~4.0.4",
"http-status-codes": "^1.3.2"
"ethers": "~4.0.4"
},
"publishConfig": {
"access": "public"

View File

@@ -6,6 +6,7 @@ import {
OrderValidatorContract,
WETH9Contract,
} from '@0x/abi-gen-wrappers';
import { assert } from '@0x/assert';
import { ContractAddresses } from '@0x/contract-addresses';
import {
Coordinator,
@@ -23,9 +24,8 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
import { SupportedProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
import { ContractWrappersConfigSchema } from './contract_wrappers_config_schema';
import { ContractWrappersConfig } from './types';
import { assert } from './utils/assert';
import { _getDefaultContractAddresses } from './utils/contract_addresses';
/**

View File

@@ -1,787 +0,0 @@
// import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
// import { Coordinator } from '@0x/contract-artifacts';
// import { schemas } from '@0x/json-schemas';
// import { generatePseudoRandomSalt, signatureUtils } from '@0x/order-utils';
// import { Order, SignedOrder, SignedZeroExTransaction, ZeroExTransaction } from '@0x/types';
// import { BigNumber, fetchAsync } from '@0x/utils';
// import { Web3Wrapper } from '@0x/web3-wrapper';
// import { ContractAbi, SupportedProvider } from 'ethereum-types';
// import * as HttpStatus from 'http-status-codes';
// import { flatten } from 'lodash';
// import { CoordinatorContract, CoordinatorRegistryContract, ExchangeContract } from '@0x/abi-gen-wrappers';
// import { orderTxOptsSchema } from './schemas/order_tx_opts_schema';
// import { txOptsSchema } from './schemas/tx_opts_schema';
// import { CoordinatorTransaction, OrderTransactionOpts } from './types';
// import { assert } from './utils/assert';
// import {
// CoordinatorServerApprovalRawResponse,
// CoordinatorServerApprovalResponse,
// CoordinatorServerCancellationResponse,
// CoordinatorServerError,
// CoordinatorServerErrorMsg,
// CoordinatorServerResponse,
// } from './utils/coordinator_server_types';
// import { decorators } from './utils/decorators';
// /**
// * This class includes all the functionality related to filling or cancelling orders through
// * the 0x V2 Coordinator extension contract.
// */
// export class CoordinatorWrapper {
// public abi: ContractAbi = Coordinator.compilerOutput.abi;
// public chainId: number;
// public address: string;
// public exchangeAddress: string;
// public registryAddress: string;
// private readonly _web3Wrapper: Web3Wrapper;
// private readonly _contractInstance: CoordinatorContract;
// private readonly _registryInstance: CoordinatorRegistryContract;
// private readonly _exchangeInstance: ExchangeContract;
// private readonly _feeRecipientToEndpoint: { [feeRecipient: string]: string } = {};
// /**
// * Instantiate CoordinatorWrapper
// * @param web3Wrapper Web3Wrapper instance to use.
// * @param chainId Desired chainId.
// * @param address The address of the Coordinator contract. If undefined, will
// * default to the known address corresponding to the chainId.
// * @param exchangeAddress The address of the Exchange contract. If undefined, will
// * default to the known address corresponding to the chainId.
// * @param registryAddress The address of the CoordinatorRegistry contract. If undefined, will
// * default to the known address corresponding to the chainId.
// */
// constructor(
// provider: SupportedProvider,
// chainId: number,
// address?: string,
// exchangeAddress?: string,
// registryAddress?: string,
// ) {
// this.chainId = chainId;
// const contractAddresses = getContractAddressesForChainOrThrow(chainId);
// this.address = address === undefined ? contractAddresses.coordinator : address;
// this.exchangeAddress = exchangeAddress === undefined ? contractAddresses.coordinator : exchangeAddress;
// this.registryAddress = registryAddress === undefined ? contractAddresses.coordinatorRegistry : registryAddress;
// this._web3Wrapper = new Web3Wrapper(provider);
// this._contractInstance = new CoordinatorContract(
// this.address,
// this._web3Wrapper.getProvider(),
// this._web3Wrapper.getContractDefaults(),
// );
// this._registryInstance = new CoordinatorRegistryContract(
// this.registryAddress,
// this._web3Wrapper.getProvider(),
// this._web3Wrapper.getContractDefaults(),
// );
// this._exchangeInstance = new ExchangeContract(
// this.exchangeAddress,
// this._web3Wrapper.getProvider(),
// this._web3Wrapper.getContractDefaults(),
// );
// }
// /**
// * Fills a signed order with an amount denominated in baseUnits of the taker asset. Under-the-hood, this
// * method uses the `feeRecipientAddress` of the order to look up the coordinator server endpoint registered in the
// * coordinator registry contract. It requests a signature from that coordinator server before
// * submitting the order and signature as a 0x transaction to the coordinator extension contract. The coordinator extension
// * contract validates signatures and then fills the order via the Exchange contract.
// * @param signedOrder An object that conforms to the SignedOrder interface.
// * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
// * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async fillOrderAsync(
// signedOrder: SignedOrder,
// takerAssetFillAmount: BigNumber,
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
// assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const data = this._exchangeInstance
// .fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
// return txHash;
// }
// /**
// * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled,
// * the fill order is abandoned.
// * @param signedOrder An object that conforms to the SignedOrder interface.
// * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
// * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async fillOrKillOrderAsync(
// signedOrder: SignedOrder,
// takerAssetFillAmount: BigNumber,
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
// assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const data = this._exchangeInstance
// .fillOrKillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, [signedOrder], orderTransactionOpts);
// return txHash;
// }
// /**
// * Batch version of fillOrderAsync. Executes multiple fills atomically in a single transaction.
// * Under-the-hood, this method uses the `feeRecipientAddress`s of the orders to looks up the coordinator server endpoints
// * registered in the coordinator registry contract. It requests a signature from each coordinator server before
// * submitting the orders and signatures as a 0x transaction to the coordinator extension contract, which validates the
// * signatures and then fills the order through the Exchange contract.
// * If any `feeRecipientAddress` in the batch is not registered to a coordinator server, the whole batch fails.
// * @param signedOrders An array of signed orders to fill.
// * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
// * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async batchFillOrdersAsync(
// signedOrders: SignedOrder[],
// takerAssetFillAmounts: BigNumber[],
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
// for (const takerAssetFillAmount of takerAssetFillAmounts) {
// assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
// }
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const signatures = signedOrders.map(o => o.signature);
// const data = this._exchangeInstance
// .batchFillOrders(signedOrders, takerAssetFillAmounts, signatures)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
// return txHash;
// }
// /**
// * No throw version of batchFillOrdersAsync
// * @param signedOrders An array of signed orders to fill.
// * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
// * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async batchFillOrdersNoThrowAsync(
// signedOrders: SignedOrder[],
// takerAssetFillAmounts: BigNumber[],
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
// for (const takerAssetFillAmount of takerAssetFillAmounts) {
// assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
// }
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const signatures = signedOrders.map(o => o.signature);
// const data = this._exchangeInstance
// .batchFillOrdersNoThrow(signedOrders, takerAssetFillAmounts, signatures)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
// return txHash;
// }
// /**
// * Batch version of fillOrKillOrderAsync. Executes multiple fills atomically in a single transaction.
// * @param signedOrders An array of signed orders to fill.
// * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
// * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async batchFillOrKillOrdersAsync(
// signedOrders: SignedOrder[],
// takerAssetFillAmounts: BigNumber[],
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
// for (const takerAssetFillAmount of takerAssetFillAmounts) {
// assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
// }
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const signatures = signedOrders.map(o => o.signature);
// const data = this._exchangeInstance
// .batchFillOrKillOrders(signedOrders, takerAssetFillAmounts, signatures)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
// return txHash;
// }
// /**
// * No throw version of marketBuyOrdersAsync
// * @param signedOrders An array of signed orders to fill.
// * @param makerAssetFillAmount Maker asset fill amount.
// * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async marketBuyOrdersNoThrowAsync(
// signedOrders: SignedOrder[],
// makerAssetFillAmount: BigNumber,
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
// assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount);
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const signatures = signedOrders.map(o => o.signature);
// const data = this._exchangeInstance
// .marketBuyOrdersNoThrow(signedOrders, makerAssetFillAmount, signatures)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
// return txHash;
// }
// /**
// * No throw version of marketSellOrdersAsync
// * @param signedOrders An array of signed orders to fill.
// * @param takerAssetFillAmount Taker asset fill amount.
// * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied
// * Provider provided at instantiation.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async marketSellOrdersNoThrowAsync(
// signedOrders: SignedOrder[],
// takerAssetFillAmount: BigNumber,
// takerAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
// assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
// assert.isETHAddressHex('takerAddress', takerAddress);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
// const signatures = signedOrders.map(o => o.signature);
// const data = this._exchangeInstance
// .marketSellOrdersNoThrow(signedOrders, takerAssetFillAmount, signatures)
// .getABIEncodedTransactionData();
// const txHash = await this._handleFillsAsync(data, takerAddress, signedOrders, orderTransactionOpts);
// return txHash;
// }
// /**
// * Soft cancel a given order.
// * Soft cancels are recorded only on coordinator operator servers and do not involve an Ethereum transaction.
// * See [soft cancels](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/coordinator-specification.md#soft-cancels).
// * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel.
// * @return CoordinatorServerCancellationResponse. See [Cancellation Response](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/coordinator-specification.md#response).
// */
// public async softCancelOrderAsync(order: Order | SignedOrder): Promise<CoordinatorServerCancellationResponse> {
// assert.doesConformToSchema('order', order, schemas.orderSchema);
// assert.isETHAddressHex('feeRecipientAddress', order.feeRecipientAddress);
// assert.isSenderAddressAsync('makerAddress', order.makerAddress, this._web3Wrapper);
// const data = this._exchangeInstance.cancelOrder(order).getABIEncodedTransactionData();
// const transaction = await this._generateSignedZeroExTransactionAsync(data, order.makerAddress);
// const endpoint = await this._getServerEndpointOrThrowAsync(order.feeRecipientAddress);
// const response = await this._executeServerRequestAsync(transaction, order.makerAddress, endpoint);
// if (response.isError) {
// const approvedOrders = new Array();
// const cancellations = new Array();
// const errors = [
// {
// ...response,
// orders: [order],
// },
// ];
// throw new CoordinatorServerError(
// CoordinatorServerErrorMsg.CancellationFailed,
// approvedOrders,
// cancellations,
// errors,
// );
// } else {
// return response.body as CoordinatorServerCancellationResponse;
// }
// }
// /**
// * Batch version of softCancelOrderAsync. Requests multiple soft cancels
// * @param orders An array of orders to cancel.
// * @return CoordinatorServerCancellationResponse. See [Cancellation Response](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/coordinator-specification.md#response).
// */
// public async batchSoftCancelOrdersAsync(orders: SignedOrder[]): Promise<CoordinatorServerCancellationResponse[]> {
// assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
// const makerAddress = getMakerAddressOrThrow(orders);
// assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
// const data = this._exchangeInstance.batchCancelOrders(orders).getABIEncodedTransactionData();
// const serverEndpointsToOrders = await this._mapServerEndpointsToOrdersAsync(orders);
// // make server requests
// const errorResponses: CoordinatorServerResponse[] = [];
// const successResponses: CoordinatorServerCancellationResponse[] = [];
// const transaction = await this._generateSignedZeroExTransactionAsync(data, makerAddress);
// for (const endpoint of Object.keys(serverEndpointsToOrders)) {
// const response = await this._executeServerRequestAsync(transaction, makerAddress, endpoint);
// if (response.isError) {
// errorResponses.push(response);
// } else {
// successResponses.push(response.body as CoordinatorServerCancellationResponse);
// }
// }
// // if no errors
// if (errorResponses.length === 0) {
// return successResponses;
// } else {
// // lookup orders with errors
// const errorsWithOrders = errorResponses.map(resp => {
// const endpoint = resp.coordinatorOperator;
// const _orders = serverEndpointsToOrders[endpoint];
// return {
// ...resp,
// orders: _orders,
// };
// });
// const approvedOrders = new Array();
// const cancellations = successResponses;
// // return errors and approvals
// throw new CoordinatorServerError(
// CoordinatorServerErrorMsg.CancellationFailed,
// approvedOrders,
// cancellations,
// errorsWithOrders,
// );
// }
// }
// /**
// * Cancels an order on-chain by submitting an Ethereum transaction.
// * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async hardCancelOrderAsync(
// order: Order | SignedOrder,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('order', order, schemas.orderSchema);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('makerAddress', order.makerAddress, this._web3Wrapper);
// const data = this._exchangeInstance.cancelOrder(order).getABIEncodedTransactionData();
// const transaction = await this._generateSignedZeroExTransactionAsync(data, order.makerAddress);
// const approvalSignatures = new Array();
// const approvalExpirationTimeSeconds = new Array();
// const txHash = await this._submitCoordinatorTransactionAsync(
// transaction,
// order.makerAddress,
// transaction.signature,
// approvalExpirationTimeSeconds,
// approvalSignatures,
// orderTransactionOpts,
// );
// return txHash;
// }
// /**
// * Batch version of hardCancelOrderAsync. Cancels orders on-chain by submitting an Ethereum transaction.
// * Executes multiple cancels atomically in a single transaction.
// * @param orders An array of orders to cancel.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async batchHardCancelOrdersAsync(
// orders: SignedOrder[],
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
// const makerAddress = getMakerAddressOrThrow(orders);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
// const data = this._exchangeInstance.batchCancelOrders(orders).getABIEncodedTransactionData();
// const transaction = await this._generateSignedZeroExTransactionAsync(data, makerAddress);
// const approvalSignatures = new Array();
// const approvalExpirationTimeSeconds = new Array();
// const txHash = await this._submitCoordinatorTransactionAsync(
// transaction,
// makerAddress,
// transaction.signature,
// approvalExpirationTimeSeconds,
// approvalSignatures,
// orderTransactionOpts,
// );
// return txHash;
// }
// /**
// * Cancels orders on-chain by submitting an Ethereum transaction.
// * Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch
// * and senderAddress equal to coordinator extension contract address.
// * @param targetOrderEpoch Target order epoch.
// * @param senderAddress Address that should send the transaction.
// * @param orderTransactionOpts Optional arguments this method accepts.
// * @return Transaction hash.
// */
// @decorators.asyncZeroExErrorHandler
// public async hardCancelOrdersUpToAsync(
// targetOrderEpoch: BigNumber,
// senderAddress: string,
// orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
// ): Promise<string> {
// assert.isBigNumber('targetOrderEpoch', targetOrderEpoch);
// assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
// const data = this._exchangeInstance.cancelOrdersUpTo(targetOrderEpoch).getABIEncodedTransactionData();
// const transaction = await this._generateSignedZeroExTransactionAsync(data, senderAddress);
// const approvalSignatures = new Array();
// const approvalExpirationTimeSeconds = new Array();
// const txHash = await this._submitCoordinatorTransactionAsync(
// transaction,
// senderAddress,
// transaction.signature,
// approvalExpirationTimeSeconds,
// approvalSignatures,
// orderTransactionOpts,
// );
// return txHash;
// }
// /**
// * Validates that the 0x transaction has been approved by all of the feeRecipients that correspond to each order in the transaction's Exchange calldata.
// * Throws an error if the transaction approvals are not valid. Will not detect failures that would occur when the transaction is executed on the Exchange contract.
// * @param transaction 0x transaction containing salt, signerAddress, and data.
// * @param txOrigin Required signer of Ethereum transaction calling this function.
// * @param transactionSignature Proof that the transaction has been signed by the signer.
// * @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
// * @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
// */
// public async assertValidCoordinatorApprovalsOrThrowAsync(
// transaction: ZeroExTransaction,
// txOrigin: string,
// transactionSignature: string,
// approvalExpirationTimeSeconds: BigNumber[],
// approvalSignatures: string[],
// ): Promise<void> {
// assert.doesConformToSchema('transaction', transaction, schemas.zeroExTransactionSchema);
// assert.isETHAddressHex('txOrigin', txOrigin);
// assert.isHexString('transactionSignature', transactionSignature);
// for (const expirationTime of approvalExpirationTimeSeconds) {
// assert.isBigNumber('expirationTime', expirationTime);
// }
// for (const approvalSignature of approvalSignatures) {
// assert.isHexString('approvalSignature', approvalSignature);
// }
// await this._contractInstance
// .assertValidCoordinatorApprovals(
// transaction,
// txOrigin,
// transactionSignature,
// approvalExpirationTimeSeconds,
// approvalSignatures,
// )
// .callAsync();
// }
// /**
// * Recovers the address of a signer given a hash and signature.
// * @param hash Any 32 byte hash.
// * @param signature Proof that the hash has been signed by signer.
// * @returns Signer address.
// */
// public async getSignerAddressAsync(hash: string, signature: string): Promise<string> {
// assert.isHexString('hash', hash);
// assert.isHexString('signature', signature);
// const signerAddress = await this._contractInstance.getSignerAddress(hash, signature).callAsync();
// return signerAddress;
// }
// private async _handleFillsAsync(
// data: string,
// takerAddress: string,
// signedOrders: SignedOrder[],
// orderTransactionOpts: OrderTransactionOpts,
// ): Promise<string> {
// const coordinatorOrders = signedOrders.filter(o => o.senderAddress === this.address);
// const serverEndpointsToOrders = await this._mapServerEndpointsToOrdersAsync(coordinatorOrders);
// // make server requests
// const errorResponses: CoordinatorServerResponse[] = [];
// const approvalResponses: CoordinatorServerResponse[] = [];
// const transaction = await this._generateSignedZeroExTransactionAsync(data, takerAddress);
// for (const endpoint of Object.keys(serverEndpointsToOrders)) {
// const response = await this._executeServerRequestAsync(transaction, takerAddress, endpoint);
// if (response.isError) {
// errorResponses.push(response);
// } else {
// approvalResponses.push(response);
// }
// }
// // if no errors
// if (errorResponses.length === 0) {
// // concatenate all approval responses
// const allApprovals = approvalResponses.map(resp =>
// formatRawResponse(resp.body as CoordinatorServerApprovalRawResponse),
// );
// const allSignatures = flatten(allApprovals.map(a => a.signatures));
// const allExpirationTimes = flatten(allApprovals.map(a => a.expirationTimeSeconds));
// // submit transaction with approvals
// const txHash = await this._submitCoordinatorTransactionAsync(
// transaction,
// takerAddress,
// transaction.signature,
// allExpirationTimes,
// allSignatures,
// orderTransactionOpts,
// );
// return txHash;
// } else {
// // format errors and approvals
// // concatenate approvals
// const notCoordinatorOrders = signedOrders.filter(o => o.senderAddress !== this.address);
// const approvedOrdersNested = approvalResponses.map(resp => {
// const endpoint = resp.coordinatorOperator;
// const orders = serverEndpointsToOrders[endpoint];
// return orders;
// });
// const approvedOrders = flatten(approvedOrdersNested.concat(notCoordinatorOrders));
// // lookup orders with errors
// const errorsWithOrders = errorResponses.map(resp => {
// const endpoint = resp.coordinatorOperator;
// const orders = serverEndpointsToOrders[endpoint];
// return {
// ...resp,
// orders,
// };
// });
// // throw informative error
// const cancellations = new Array();
// throw new CoordinatorServerError(
// CoordinatorServerErrorMsg.FillFailed,
// approvedOrders,
// cancellations,
// errorsWithOrders,
// );
// }
// function formatRawResponse(
// rawResponse: CoordinatorServerApprovalRawResponse,
// ): CoordinatorServerApprovalResponse {
// return {
// signatures: ([] as string[]).concat(rawResponse.signatures),
// expirationTimeSeconds: ([] as BigNumber[]).concat(
// Array(rawResponse.signatures.length).fill(rawResponse.expirationTimeSeconds),
// ),
// };
// }
// }
// private async _getServerEndpointOrThrowAsync(feeRecipientAddress: string): Promise<string> {
// const cached = this._feeRecipientToEndpoint[feeRecipientAddress];
// const endpoint =
// cached !== undefined
// ? cached
// : await _fetchServerEndpointOrThrowAsync(feeRecipientAddress, this._registryInstance);
// return endpoint;
// async function _fetchServerEndpointOrThrowAsync(
// feeRecipient: string,
// registryInstance: CoordinatorRegistryContract,
// ): Promise<string> {
// const coordinatorOperatorEndpoint = await registryInstance.getCoordinatorEndpoint(feeRecipient).callAsync();
// if (coordinatorOperatorEndpoint === '' || coordinatorOperatorEndpoint === undefined) {
// throw new Error(
// `No Coordinator server endpoint found in Coordinator Registry for feeRecipientAddress: ${feeRecipient}. Registry contract address: ${
// registryInstance.address
// }`,
// );
// }
// return coordinatorOperatorEndpoint;
// }
// }
// private async _generateSignedZeroExTransactionAsync(
// data: string,
// signerAddress: string,
// ): Promise<SignedZeroExTransaction> {
// const transaction: ZeroExTransaction = {
// salt: generatePseudoRandomSalt(),
// signerAddress,
// data,
// domain: {
// verifyingContract: this.exchangeAddress,
// chainId: await this._web3Wrapper.getChainIdAsync(),
// },
// // HACK (xianny): arbitrary numbers for now
// expirationTimeSeconds: new BigNumber(5),
// gasPrice: new BigNumber(1),
// };
// const signedTransaction = await signatureUtils.ecSignTransactionAsync(
// this._web3Wrapper.getProvider(),
// transaction,
// transaction.signerAddress,
// );
// return signedTransaction;
// }
// private async _executeServerRequestAsync(
// signedTransaction: SignedZeroExTransaction,
// txOrigin: string,
// endpoint: string,
// ): Promise<CoordinatorServerResponse> {
// const requestPayload = {
// signedTransaction,
// txOrigin,
// };
// const response = await fetchAsync(`${endpoint}/v1/request_transaction?chainId=${this.chainId}`, {
// body: JSON.stringify(requestPayload),
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json; charset=utf-8',
// },
// });
// const isError = response.status !== HttpStatus.OK;
// const isValidationError = response.status === HttpStatus.BAD_REQUEST;
// const json = isError && !isValidationError ? undefined : await response.json();
// const result = {
// isError,
// status: response.status,
// body: isError ? undefined : json,
// error: isError ? json : undefined,
// request: requestPayload,
// coordinatorOperator: endpoint,
// };
// return result;
// }
// private async _submitCoordinatorTransactionAsync(
// transaction: CoordinatorTransaction,
// txOrigin: string,
// transactionSignature: string,
// approvalExpirationTimeSeconds: BigNumber[],
// approvalSignatures: string[],
// orderTransactionOpts: OrderTransactionOpts,
// ): Promise<string> {
// if (orderTransactionOpts.shouldValidate) {
// await this._contractInstance
// .executeTransaction(
// transaction,
// txOrigin,
// transactionSignature,
// approvalExpirationTimeSeconds,
// approvalSignatures,
// )
// .callAsync({
// from: txOrigin,
// gas: orderTransactionOpts.gasLimit,
// gasPrice: orderTransactionOpts.gasPrice,
// nonce: orderTransactionOpts.nonce,
// });
// }
// const txHash = await this._contractInstance
// .executeTransaction(
// transaction,
// txOrigin,
// transactionSignature,
// approvalExpirationTimeSeconds,
// approvalSignatures,
// )
// .sendTransactionAsync({
// from: txOrigin,
// gas: orderTransactionOpts.gasLimit,
// gasPrice: orderTransactionOpts.gasPrice,
// nonce: orderTransactionOpts.nonce,
// });
// return txHash;
// }
// private async _mapServerEndpointsToOrdersAsync(
// coordinatorOrders: SignedOrder[],
// ): Promise<{ [endpoint: string]: SignedOrder[] }> {
// const feeRecipientsToOrders: { [feeRecipient: string]: SignedOrder[] } = {};
// for (const order of coordinatorOrders) {
// const feeRecipient = order.feeRecipientAddress;
// if (feeRecipientsToOrders[feeRecipient] === undefined) {
// feeRecipientsToOrders[feeRecipient] = [] as SignedOrder[];
// }
// feeRecipientsToOrders[feeRecipient].push(order);
// }
// const serverEndpointsToOrders: { [endpoint: string]: SignedOrder[] } = {};
// for (const feeRecipient of Object.keys(feeRecipientsToOrders)) {
// const endpoint = await this._getServerEndpointOrThrowAsync(feeRecipient);
// const orders = feeRecipientsToOrders[feeRecipient];
// if (serverEndpointsToOrders[endpoint] === undefined) {
// serverEndpointsToOrders[endpoint] = [];
// }
// serverEndpointsToOrders[endpoint] = serverEndpointsToOrders[endpoint].concat(orders);
// }
// return serverEndpointsToOrders;
// }
// }
// function getMakerAddressOrThrow(orders: Array<Order | SignedOrder>): string {
// const uniqueMakerAddresses = new Set(orders.map(o => o.makerAddress));
// if (uniqueMakerAddresses.size > 1) {
// throw new Error(`All orders in a batch must have the same makerAddress`);
// }
// return orders[0].makerAddress;
// }
// tslint:disable:max-file-line-count

View File

@@ -55,17 +55,7 @@ export {
ExchangeTransactionExecutionEventArgs,
} from '@0x/abi-gen-wrappers';
export {
OrderStatus,
ContractError,
ForwarderError,
CoordinatorServerCancellationResponse,
CoordinatorServerError,
ContractWrappersConfig,
OrderTransactionOpts,
TransactionOpts,
OrderInfo,
} from './types';
export { OrderStatus, ContractError, ForwarderError, ContractWrappersConfig, OrderInfo } from './types';
export {
BlockRange,

View File

@@ -1,8 +0,0 @@
export const orderTxOptsSchema = {
id: '/OrderTxOpts',
allOf: [{ $ref: '/TxOpts' }],
properties: {
shouldValidate: { type: 'boolean' },
},
type: 'object',
};

View File

@@ -1,9 +0,0 @@
export const txOptsSchema = {
id: '/TxOpts',
properties: {
gasPrice: { $ref: '/numberSchema' },
gasLimit: { type: 'number' },
nonce: { type: 'number' },
},
type: 'object',
};

View File

@@ -1,13 +1,6 @@
import { ContractAddresses } from '@0x/contract-addresses';
import { BigNumber } from '@0x/utils';
export interface TxOpts {
from: string;
gas?: number;
value?: BigNumber;
gasPrice?: BigNumber;
}
export enum ForwarderError {
CompleteFillFailed = 'COMPLETE_FILL_FAILED',
}
@@ -40,27 +33,6 @@ export interface ContractWrappersConfig {
blockPollingIntervalMs?: number;
}
// TODO(xianny): remove after refactoring coordinator wrapper
/**
* gasPrice: Gas price in Wei to use for a transaction
* gasLimit: The amount of gas to send with a transaction (in Gwei)
* nonce: The nonce to use for a transaction. If not specified, it defaults to the next incremented nonce.
*/
export interface TransactionOpts {
gasPrice?: BigNumber;
gasLimit?: number;
nonce?: number;
}
// TODO(xianny): remove after refactoring coordinator wrapper
/**
* shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before
* broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true.
*/
export interface OrderTransactionOpts extends TransactionOpts {
shouldValidate?: boolean;
}
export interface OrderInfo {
orderStatus: OrderStatus;
orderHash: string;
@@ -92,11 +64,3 @@ export interface OrderAndTraderInfo {
orderInfo: OrderInfo;
traderInfo: TraderInfo;
}
export { CoordinatorServerCancellationResponse, CoordinatorServerError } from './utils/coordinator_server_types';
export interface CoordinatorTransaction {
salt: BigNumber;
signerAddress: string;
data: string;
}

View File

@@ -1,23 +0,0 @@
import { assert as sharedAssert } from '@0x/assert';
// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here
import { Schema } from '@0x/json-schemas'; // tslint:disable-line:no-unused-variable
import { Order } from '@0x/types'; // tslint:disable-line:no-unused-variable
import { BigNumber } from '@0x/utils'; // tslint:disable-line:no-unused-variable
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash';
export const assert = {
...sharedAssert,
async isSenderAddressAsync(
variableName: string,
senderAddressHex: string,
web3Wrapper: Web3Wrapper,
): Promise<void> {
sharedAssert.isETHAddressHex(variableName, senderAddressHex);
const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
sharedAssert.assert(
isSenderAddressAvailable,
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
);
},
};

View File

@@ -1,61 +0,0 @@
import { Order, SignedOrder, SignedZeroExTransaction } from '@0x/types';
import { BigNumber } from '@0x/utils';
export interface CoordinatorServerApprovalResponse {
signatures: string[];
expirationTimeSeconds: BigNumber[];
}
export interface CoordinatorServerApprovalRawResponse {
signatures: string[];
expirationTimeSeconds: BigNumber;
}
export interface CoordinatorServerCancellationResponse {
outstandingFillSignatures: CoordinatorOutstandingFillSignatures[];
cancellationSignatures: string[];
}
export interface CoordinatorOutstandingFillSignatures {
orderHash: string;
approvalSignatures: string[];
expirationTimeSeconds: BigNumber;
takerAssetFillAmount: BigNumber;
}
export interface CoordinatorServerResponse {
isError: boolean;
status: number;
body?: CoordinatorServerCancellationResponse | CoordinatorServerApprovalRawResponse;
error?: any;
request: CoordinatorServerRequest;
coordinatorOperator: string;
orders?: Array<SignedOrder | Order>;
}
export interface CoordinatorServerRequest {
signedTransaction: SignedZeroExTransaction;
txOrigin: string;
}
export class CoordinatorServerError extends Error {
public message: CoordinatorServerErrorMsg;
public approvedOrders?: SignedOrder[] = [];
public cancellations?: CoordinatorServerCancellationResponse[] = [];
public errors: CoordinatorServerResponse[];
constructor(
message: CoordinatorServerErrorMsg,
approvedOrders: SignedOrder[],
cancellations: CoordinatorServerCancellationResponse[],
errors: CoordinatorServerResponse[],
) {
super();
this.message = message;
this.approvedOrders = approvedOrders;
this.cancellations = cancellations;
this.errors = errors;
}
}
export enum CoordinatorServerErrorMsg {
CancellationFailed = 'Failed to cancel with some coordinator server(s). See errors for more info. See cancellations for successful cancellations.',
FillFailed = 'Failed to obtain approval signatures from some coordinator server(s). See errors for more info. Current transaction has been abandoned but you may resubmit with only approvedOrders (a new ZeroEx transaction will have to be signed).',
}

View File

@@ -1,133 +0,0 @@
import * as _ from 'lodash';
export enum ContractError {
ContractNotDeployedOnChain = 'CONTRACT_NOT_DEPLOYED_ON_CHAIN',
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
InvalidJump = 'INVALID_JUMP',
OutOfGas = 'OUT_OF_GAS',
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND',
ERC721NoApproval = 'ERC_721_NO_APPROVAL',
SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED',
}
export type AsyncMethod = (...args: any[]) => Promise<any>;
export type SyncMethod = (...args: any[]) => any;
const constants = {
INVALID_JUMP_PATTERN: 'invalid JUMP at',
REVERT: 'revert',
OUT_OF_GAS_PATTERN: 'out of gas',
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
METAMASK_USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature',
TRUST_WALLET_USER_DENIED_SIGNATURE_PATTERN: 'cancelled',
};
type ErrorTransformer = (err: Error) => Error;
const contractCallErrorTransformer = (error: Error) => {
if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) {
return new Error(ContractError.InvalidJump);
}
if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) {
return new Error(ContractError.OutOfGas);
}
if (_.includes(error.message, constants.REVERT)) {
const revertReason = error.message.split(constants.REVERT)[1].trim();
return new Error(revertReason);
}
return error;
};
const schemaErrorTransformer = (error: Error) => {
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
const errMsg =
'Order taker must be of type string. If you want anyone to be able to fill an order - pass NULL_ADDRESS';
return new Error(errMsg);
}
return error;
};
const signatureRequestErrorTransformer = (error: Error) => {
if (
_.includes(error.message, constants.METAMASK_USER_DENIED_SIGNATURE_PATTERN) ||
_.includes(error.message, constants.TRUST_WALLET_USER_DENIED_SIGNATURE_PATTERN)
) {
const errMsg = ContractError.SignatureRequestDenied;
return new Error(errMsg);
}
return error;
};
/**
* Source: https://stackoverflow.com/a/29837695/3546986
*/
const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
const asyncErrorHandlingDecorator = (
_target: object,
_key: string | symbol,
descriptor: TypedPropertyDescriptor<AsyncMethod>,
) => {
const originalMethod = descriptor.value as AsyncMethod;
// Do not use arrow syntax here. Use a function expression in
// order to use the correct value of `this` in this method
// tslint:disable-next-line:only-arrow-functions
descriptor.value = async function(...args: any[]): Promise<any> {
try {
const result = await originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this
return result;
} catch (error) {
const transformedError = errorTransformer(error);
throw transformedError;
}
};
return descriptor;
};
return asyncErrorHandlingDecorator;
};
const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
const syncErrorHandlingDecorator = (
_target: object,
_key: string | symbol,
descriptor: TypedPropertyDescriptor<SyncMethod>,
) => {
const originalMethod = descriptor.value as SyncMethod;
// Do not use arrow syntax here. Use a function expression in
// order to use the correct value of `this` in this method
// tslint:disable-next-line:only-arrow-functions
descriptor.value = function(...args: any[]): any {
try {
const result = originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this
return result;
} catch (error) {
const transformedError = errorTransformer(error);
throw transformedError;
}
};
return descriptor;
};
return syncErrorHandlingDecorator;
};
// _.flow(f, g) = f ∘ g
const zeroExErrorTransformer = _.flow(
schemaErrorTransformer,
contractCallErrorTransformer,
signatureRequestErrorTransformer,
);
export const decorators = {
asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer),
syncZeroExErrorHandler: syncErrorHandlerFactory(zeroExErrorTransformer),
};

View File

@@ -1,5 +1,6 @@
import { constants, OrderFactory } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { migrateOnceAsync } from '@0x/migrations';
import { SignedOrder } from '@0x/types';
import { addressUtils, BigNumber } from '@0x/utils';
import * as chai from 'chai';
@@ -9,7 +10,6 @@ import 'mocha';
import { ContractAddresses, ContractWrappers } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { migrateOnceAsync } from './utils/migrate';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();

View File

@@ -1,675 +0,0 @@
// import { constants, OrderFactory } from '@0x/contracts-test-utils';
// import { defaultOrmConfig, getAppAsync } from '@0x/coordinator-server';
// import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
// import { SignedOrder } from '@0x/types';
// import { BigNumber, fetchAsync, logUtils, providerUtils } from '@0x/utils';
// import * as chai from 'chai';
// import * as http from 'http';
// import 'mocha';
// import * as nock from 'nock';
// import { ContractWrappers } from '../src';
// import { CoordinatorRegistryContract } from '../src/index';
// import { CoordinatorServerErrorMsg } from '../src/utils/coordinator_server_types';
// import { chaiSetup } from './utils/chai_setup';
// import { migrateOnceAsync } from './utils/migrate';
// import { provider, web3Wrapper } from './utils/web3_wrapper';
// chaiSetup.configure();
// const expect = chai.expect;
// const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// const coordinatorPort = '3000';
// const anotherCoordinatorPort = '4000';
// const coordinatorEndpoint = 'http://localhost:';
// // tslint:disable:custom-no-magic-numbers
// // TODO (xianny): coordinator server must be updated to take new SignedOrder format. it returns all errors at the moment
// describe.skip('CoordinatorWrapper', () => {
// const takerTokenFillAmount = new BigNumber(5);
// let chainId: number;
// let coordinatorServerApp: http.Server;
// let anotherCoordinatorServerApp: http.Server;
// let contractWrappers: ContractWrappers;
// let orderFactory: OrderFactory;
// let exchangeContractAddress: string;
// let userAddresses: string[];
// let makerAddress: string;
// let takerAddress: string;
// let feeRecipientAddressOne: string;
// let feeRecipientAddressTwo: string;
// let feeRecipientAddressThree: string;
// let feeRecipientAddressFour: string;
// let makerTokenAddress: string;
// let takerTokenAddress: string;
// let feeTokenAddress: string;
// let makerAssetData: string;
// let takerAssetData: string;
// let feeAssetData: string;
// let txHash: string;
// let signedOrder: SignedOrder;
// let anotherSignedOrder: SignedOrder;
// let signedOrderWithDifferentFeeRecipient: SignedOrder;
// let signedOrderWithDifferentCoordinatorOperator: SignedOrder;
// let coordinatorRegistryInstance: CoordinatorRegistryContract;
// // for testing server error responses
// let serverValidationError: any;
// let serverCancellationSuccess: any;
// let serverApprovalSuccess: any;
// before(async () => {
// const contractAddresses = await migrateOnceAsync();
// await blockchainLifecycle.startAsync();
// const config = {
// chainId: constants.TESTRPC_CHAIN_ID,
// contractAddresses,
// blockPollingIntervalMs: 10,
// };
// contractWrappers = new ContractWrappers(provider, config);
// chainId = await providerUtils.getChainIdAsync(provider);
// exchangeContractAddress = contractWrappers.exchange.address;
// userAddresses = await web3Wrapper.getAvailableAddressesAsync();
// [
// ,
// makerAddress,
// takerAddress,
// feeRecipientAddressOne,
// feeRecipientAddressTwo,
// feeRecipientAddressThree,
// feeRecipientAddressFour,
// ] = userAddresses.slice(0, 7);
// [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
// feeTokenAddress = contractAddresses.zrxToken;
// [makerAssetData, takerAssetData, feeAssetData] = [
// await contractWrappers.devUtils.encodeERC20AssetData(makerTokenAddress).callAsync(),
// await contractWrappers.devUtils.encodeERC20AssetData(takerTokenAddress).callAsync(),
// await contractWrappers.devUtils.encodeERC20AssetData(feeTokenAddress).callAsync(),
// ];
// // Configure order defaults
// const defaultOrderParams = {
// ...constants.STATIC_ORDER_PARAMS,
// makerAddress,
// feeRecipientAddress: feeRecipientAddressOne,
// makerAssetData,
// takerAssetData,
// makerFeeAssetData: feeAssetData,
// takerFeeAssetData: feeAssetData,
// senderAddress: contractAddresses.coordinator,
// exchangeAddress: exchangeContractAddress,
// chainId,
// };
// const privateKey = constants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
// orderFactory = new OrderFactory(privateKey, defaultOrderParams);
// // set up mock coordinator server
// const coordinatorServerConfigs = {
// HTTP_PORT: 3000, // Only used in default instantiation in 0x-coordinator-server/server.js; not used here
// NETWORK_ID_TO_SETTINGS: {
// // TODO: change to CHAIN_ID_TO_SETTINGS when @0x/coordinator-server is ready
// [config.chainId]: {
// FEE_RECIPIENTS: [
// {
// ADDRESS: feeRecipientAddressOne,
// PRIVATE_KEY: constants.TESTRPC_PRIVATE_KEYS[
// userAddresses.indexOf(feeRecipientAddressOne)
// ].toString('hex'),
// },
// {
// ADDRESS: feeRecipientAddressTwo,
// PRIVATE_KEY: constants.TESTRPC_PRIVATE_KEYS[
// userAddresses.indexOf(feeRecipientAddressTwo)
// ].toString('hex'),
// },
// {
// ADDRESS: feeRecipientAddressThree,
// PRIVATE_KEY: constants.TESTRPC_PRIVATE_KEYS[
// userAddresses.indexOf(feeRecipientAddressThree)
// ].toString('hex'),
// },
// ],
// // Ethereum RPC url, only used in the default instantiation in 0x-coordinator-server/server.js
// // Not used here when instantiating with the imported app
// RPC_URL: 'http://ignore',
// },
// },
// NETWORK_ID_TO_CONTRACT_ADDRESSES: {
// // TODO: change to CHAIN_ID_TO_CONTRACT_ADDRESSES when @0x/coordinator-server is ready
// [config.chainId]: contractAddresses,
// },
// // Optional selective delay on fill requests
// SELECTIVE_DELAY_MS: 0,
// EXPIRATION_DURATION_SECONDS: 60, // 1 minute
// };
// coordinatorServerApp = await getAppAsync(
// {
// [config.chainId]: provider,
// },
// coordinatorServerConfigs,
// {
// name: 'coord_server_1',
// type: 'sqlite',
// database: ':memory:',
// entities: defaultOrmConfig.entities,
// cli: defaultOrmConfig.cli,
// logging: defaultOrmConfig.logging,
// synchronize: defaultOrmConfig.synchronize,
// },
// );
// coordinatorServerApp.listen(coordinatorPort, () => {
// logUtils.log(`Coordinator SERVER API (HTTP) listening on port ${coordinatorPort}!`);
// });
// anotherCoordinatorServerApp = await getAppAsync(
// {
// [config.chainId]: provider,
// },
// coordinatorServerConfigs,
// {
// type: 'sqlite',
// name: 'coord_server_2',
// database: ':memory:',
// entities: defaultOrmConfig.entities,
// cli: defaultOrmConfig.cli,
// logging: defaultOrmConfig.logging,
// synchronize: defaultOrmConfig.synchronize,
// },
// );
// anotherCoordinatorServerApp.listen(anotherCoordinatorPort, () => {
// logUtils.log(`Coordinator SERVER API (HTTP) listening on port ${anotherCoordinatorPort}!`);
// });
// // setup coordinator registry
// coordinatorRegistryInstance = new CoordinatorRegistryContract(contractAddresses.coordinatorRegistry, provider);
// // register coordinator server
// await web3Wrapper.awaitTransactionSuccessAsync(
// await coordinatorRegistryInstance
// .setCoordinatorEndpoint(`${coordinatorEndpoint}${coordinatorPort}`)
// .sendTransactionAsync({
// from: feeRecipientAddressOne,
// }),
// constants.AWAIT_TRANSACTION_MINED_MS,
// );
// await web3Wrapper.awaitTransactionSuccessAsync(
// await coordinatorRegistryInstance
// .setCoordinatorEndpoint(`${coordinatorEndpoint}${coordinatorPort}`)
// .sendTransactionAsync({
// from: feeRecipientAddressTwo,
// }),
// constants.AWAIT_TRANSACTION_MINED_MS,
// );
// // register another coordinator server
// await web3Wrapper.awaitTransactionSuccessAsync(
// await coordinatorRegistryInstance
// .setCoordinatorEndpoint(`${coordinatorEndpoint}${anotherCoordinatorPort}`)
// .sendTransactionAsync({
// from: feeRecipientAddressThree,
// }),
// constants.AWAIT_TRANSACTION_MINED_MS,
// );
// });
// after(async () => {
// await blockchainLifecycle.revertAsync();
// });
// beforeEach(async () => {
// await blockchainLifecycle.startAsync();
// signedOrder = await orderFactory.newSignedOrderAsync();
// anotherSignedOrder = await orderFactory.newSignedOrderAsync();
// signedOrderWithDifferentFeeRecipient = await orderFactory.newSignedOrderAsync({
// feeRecipientAddress: feeRecipientAddressTwo,
// });
// signedOrderWithDifferentCoordinatorOperator = await orderFactory.newSignedOrderAsync({
// feeRecipientAddress: feeRecipientAddressThree,
// });
// });
// afterEach(async () => {
// await blockchainLifecycle.revertAsync();
// });
// describe('test setup', () => {
// it('should have coordinator registry which returns an endpoint', async () => {
// const setCoordinatorEndpoint = await coordinatorRegistryInstance
// .getCoordinatorEndpoint(feeRecipientAddressOne)
// .callAsync();
// const anotherSetCoordinatorEndpoint = await coordinatorRegistryInstance
// .getCoordinatorEndpoint(feeRecipientAddressThree)
// .callAsync();
// expect(setCoordinatorEndpoint).to.be.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// expect(anotherSetCoordinatorEndpoint).to.be.equal(`${coordinatorEndpoint}${anotherCoordinatorPort}`);
// });
// it('should have coordinator server endpoints which respond to pings', async () => {
// let result = await fetchAsync(`${coordinatorEndpoint}${coordinatorPort}/v1/ping`);
// expect(result.status).to.be.equal(200);
// expect(await result.text()).to.be.equal('pong');
// result = await fetchAsync(`${coordinatorEndpoint}${anotherCoordinatorPort}/v1/ping`);
// expect(result.status).to.be.equal(200);
// expect(await result.text()).to.be.equal('pong');
// });
// });
// // fill handling is the same for all fill methods so we can test them all through the fillOrder and batchFillOrders interfaces
// describe('fill order(s)', () => {
// describe('#fillOrderAsync', () => {
// it('should fill a valid order', async () => {
// txHash = await contractWrappers.coordinator.fillOrderAsync(
// signedOrder,
// takerTokenFillAmount,
// takerAddress,
// );
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// });
// describe('#batchFillOrdersAsync', () => {
// it('should fill a batch of valid orders', async () => {
// const signedOrders = [signedOrder, anotherSignedOrder];
// const takerAssetFillAmounts = Array(2).fill(takerTokenFillAmount);
// txHash = await contractWrappers.coordinator.batchFillOrdersAsync(
// signedOrders,
// takerAssetFillAmounts,
// takerAddress,
// );
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// it('should fill a batch of orders with different feeRecipientAddresses with the same coordinator server', async () => {
// const signedOrders = [signedOrder, anotherSignedOrder, signedOrderWithDifferentFeeRecipient];
// const takerAssetFillAmounts = Array(3).fill(takerTokenFillAmount);
// txHash = await contractWrappers.coordinator.batchFillOrdersAsync(
// signedOrders,
// takerAssetFillAmounts,
// takerAddress,
// );
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// // coordinator-server, as currently implemented, shares a singleton database connection across
// // all instantiations. Making the request to two different mocked server endpoints still hits the
// // same database and fails because of the uniqueness constraint on transactions in the database.
// it.skip('should fill a batch of orders with different feeRecipientAddresses with different coordinator servers', async () => {
// const signedOrders = [
// signedOrder,
// anotherSignedOrder,
// signedOrderWithDifferentFeeRecipient,
// signedOrderWithDifferentCoordinatorOperator,
// ];
// const takerAssetFillAmounts = Array(4).fill(takerTokenFillAmount);
// txHash = await contractWrappers.coordinator.batchFillOrdersAsync(
// signedOrders,
// takerAssetFillAmounts,
// takerAddress,
// );
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// it('should fill a batch of mixed coordinator and non-coordinator orders', async () => {
// const nonCoordinatorOrder = await orderFactory.newSignedOrderAsync({
// senderAddress: constants.NULL_ADDRESS,
// });
// const signedOrders = [signedOrder, nonCoordinatorOrder];
// const takerAssetFillAmounts = Array(2).fill(takerTokenFillAmount);
// txHash = await contractWrappers.coordinator.batchFillOrdersAsync(
// signedOrders,
// takerAssetFillAmounts,
// takerAddress,
// );
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// });
// });
// describe('soft cancel order(s)', () => {
// describe('#softCancelOrderAsync', () => {
// it('should soft cancel a valid order', async () => {
// const response = await contractWrappers.coordinator.softCancelOrderAsync(signedOrder);
// expect(response.outstandingFillSignatures).to.have.lengthOf(0);
// expect(response.cancellationSignatures).to.have.lengthOf(1);
// });
// });
// describe('#batchSoftCancelOrdersAsync', () => {
// it('should soft cancel a batch of valid orders', async () => {
// const orders = [signedOrder, anotherSignedOrder];
// const response = await contractWrappers.coordinator.batchSoftCancelOrdersAsync(orders);
// expect(response).to.have.lengthOf(1);
// expect(response[0].outstandingFillSignatures).to.have.lengthOf(0);
// expect(response[0].cancellationSignatures).to.have.lengthOf(1);
// });
// it('should soft cancel a batch of orders with different feeRecipientAddresses', async () => {
// const orders = [signedOrder, anotherSignedOrder, signedOrderWithDifferentFeeRecipient];
// const response = await contractWrappers.coordinator.batchSoftCancelOrdersAsync(orders);
// expect(response).to.have.lengthOf(1);
// expect(response[0].outstandingFillSignatures).to.have.lengthOf(0);
// expect(response[0].cancellationSignatures).to.have.lengthOf(2);
// });
// it('should soft cancel a batch of orders with different coordinatorOperator and concatenate responses', async () => {
// const orders = [
// signedOrder,
// anotherSignedOrder,
// signedOrderWithDifferentFeeRecipient,
// signedOrderWithDifferentCoordinatorOperator,
// ];
// const response = await contractWrappers.coordinator.batchSoftCancelOrdersAsync(orders);
// expect(response).to.have.lengthOf(2);
// expect(response[0].outstandingFillSignatures).to.have.lengthOf(0);
// expect(response[0].cancellationSignatures).to.have.lengthOf(3);
// expect(response[1].cancellationSignatures).to.have.lengthOf(3); // both coordinator servers support the same feeRecipients
// });
// });
// });
// describe('hard cancel order(s)', () => {
// describe('#hardCancelOrderAsync', () => {
// it('should hard cancel a valid order', async () => {
// txHash = await contractWrappers.coordinator.hardCancelOrderAsync(signedOrder);
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// });
// describe('#batchHardCancelOrdersAsync', () => {
// it('should hard cancel a batch of valid orders', async () => {
// const orders = [signedOrder, anotherSignedOrder];
// txHash = await contractWrappers.coordinator.batchHardCancelOrdersAsync(orders);
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// });
// });
// describe('#cancelOrdersUpTo/getOrderEpochAsync', () => {
// it('should hard cancel orders up to target order epoch', async () => {
// const targetOrderEpoch = new BigNumber(42);
// txHash = await contractWrappers.coordinator.hardCancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
// await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
// const orderEpoch = await contractWrappers.exchange
// .orderEpoch(makerAddress, contractWrappers.coordinator.address)
// .callAsync();
// expect(orderEpoch).to.be.bignumber.equal(targetOrderEpoch.plus(1));
// });
// });
// });
// describe('coordinator edge cases', () => {
// it('should throw error when feeRecipientAddress is not in registry', async () => {
// const badOrder = await orderFactory.newSignedOrderAsync({
// feeRecipientAddress: feeRecipientAddressFour,
// });
// expect(
// contractWrappers.coordinator.fillOrderAsync(badOrder, takerTokenFillAmount, takerAddress),
// ).to.be.rejected();
// });
// it('should throw error when coordinator endpoint is malformed', async () => {
// await web3Wrapper.awaitTransactionSuccessAsync(
// await coordinatorRegistryInstance.setCoordinatorEndpoint('localhost').sendTransactionAsync({
// from: feeRecipientAddressFour,
// }),
// constants.AWAIT_TRANSACTION_MINED_MS,
// );
// expect(
// contractWrappers.coordinator.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress),
// ).to.be.rejected();
// });
// });
// describe('coordinator server errors', () => {
// beforeEach('setup', () => {
// serverValidationError = {
// code: 100,
// reason: 'Validation Failed',
// validationErrors: [
// {
// field: 'signedTransaction',
// code: 1011,
// reason:
// 'A transaction can only be approved once. To request approval to perform the same actions, generate and sign an identical transaction with a different salt value.',
// },
// ],
// };
// serverCancellationSuccess = {
// outstandingFillSignatures: [
// {
// orderHash: '0xd1dc61f3e7e5f41d72beae7863487beea108971de678ca00d903756f842ef3ce',
// approvalSignatures: [
// '0x1c7383ca8ebd6de8b5b20b1c2d49bea166df7dfe4af1932c9c52ec07334e859cf2176901da35f4480ceb3ab63d8d0339d851c31929c40d88752689b9a8a535671303',
// ],
// expirationTimeSeconds: 1552390380,
// takerAssetFillAmount: 100000000000000000000,
// },
// ],
// cancellationSignatures: [
// '0x2ea3117a8ebd6de8b5b20b1c2d49bea166df7dfe4af1932c9c52ec07334e859cf2176901da35f4480ceb3ab63d8d0339d851c31929c40d88752689b9a855b5a7b401',
// ],
// };
// serverApprovalSuccess = {
// signatures: [
// '0x1cc07d7ae39679690a91418d46491520f058e4fb14debdf2e98f2376b3970de8512ace44af0be6d1c65617f7aae8c2364ff63f241515ee1559c3eeecb0f671d9e903',
// ],
// expirationTimeSeconds: 1552390014,
// };
// nock(`${coordinatorEndpoint}${coordinatorPort}`)
// .post('/v1/request_transaction', () => true)
// .query({
// chainId: 1337,
// })
// .reply(400, serverValidationError);
// });
// it('should throw error when softCancel fails', done => {
// contractWrappers.coordinator
// .softCancelOrderAsync(signedOrder)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.CancellationFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal([signedOrder]);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// done();
// });
// });
// it('should throw error when batch soft cancel fails with single coordinator operator', done => {
// const orders = [signedOrder, signedOrderWithDifferentFeeRecipient];
// contractWrappers.coordinator
// .batchSoftCancelOrdersAsync(orders)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.CancellationFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal(orders);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// done();
// });
// });
// it('should throw consolidated error when batch soft cancel partially fails with different coordinator operators', done => {
// nock(`${coordinatorEndpoint}${anotherCoordinatorPort}`)
// .post('/v1/request_transaction', () => true)
// .query({
// chainId: 1337,
// })
// .reply(200, serverCancellationSuccess);
// const signedOrders = [signedOrder, signedOrderWithDifferentCoordinatorOperator];
// contractWrappers.coordinator
// .batchSoftCancelOrdersAsync(signedOrders)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.CancellationFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.deep.equal([serverCancellationSuccess]);
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal([signedOrder]);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// done();
// });
// });
// it('should throw consolidated error when batch soft cancel totally fails with different coordinator operators', done => {
// nock(`${coordinatorEndpoint}${anotherCoordinatorPort}`)
// .post('/v1/request_transaction', () => true)
// .query({
// chainId: 1337,
// })
// .reply(400, serverValidationError);
// const signedOrders = [signedOrder, signedOrderWithDifferentCoordinatorOperator];
// contractWrappers.coordinator
// .batchSoftCancelOrdersAsync(signedOrders)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.CancellationFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal([signedOrder]);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// const anotherErrorBody = err.errors[1];
// expect(anotherErrorBody.isError).to.be.true();
// expect(anotherErrorBody.status).to.equal(400);
// expect(anotherErrorBody.error).to.deep.equal(serverValidationError);
// expect(anotherErrorBody.orders).to.deep.equal([signedOrderWithDifferentCoordinatorOperator]);
// expect(anotherErrorBody.coordinatorOperator).to.equal(
// `${coordinatorEndpoint}${anotherCoordinatorPort}`,
// );
// done();
// });
// });
// it('should throw error when a fill fails', done => {
// contractWrappers.coordinator
// .fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.FillFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal([signedOrder]);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// done();
// });
// });
// it('should throw error when batch fill fails with single coordinator operator', done => {
// const signedOrders = [signedOrder, signedOrderWithDifferentFeeRecipient];
// const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount, takerTokenFillAmount];
// contractWrappers.coordinator
// .batchFillOrdersAsync(signedOrders, takerAssetFillAmounts, takerAddress)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.FillFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal(signedOrders);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// done();
// });
// });
// it('should throw consolidated error when batch fill partially fails with different coordinator operators', done => {
// nock(`${coordinatorEndpoint}${anotherCoordinatorPort}`)
// .post('/v1/request_transaction', () => true)
// .query({
// chainId: 1337,
// })
// .reply(200, serverApprovalSuccess);
// const signedOrders = [signedOrder, signedOrderWithDifferentCoordinatorOperator];
// const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount, takerTokenFillAmount];
// contractWrappers.coordinator
// .batchFillOrdersAsync(signedOrders, takerAssetFillAmounts, takerAddress)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.FillFailed);
// expect(err.approvedOrders).to.deep.equal([signedOrderWithDifferentCoordinatorOperator]);
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal([signedOrder]);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// done();
// });
// });
// it('should throw consolidated error when batch fill totally fails with different coordinator operators', done => {
// nock(`${coordinatorEndpoint}${anotherCoordinatorPort}`)
// .post('/v1/request_transaction', () => true)
// .query({
// chainId: 1337,
// })
// .reply(400, serverValidationError);
// const signedOrders = [signedOrder, signedOrderWithDifferentCoordinatorOperator];
// const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount, takerTokenFillAmount];
// contractWrappers.coordinator
// .batchFillOrdersAsync(signedOrders, takerAssetFillAmounts, takerAddress)
// .then(res => {
// expect(res).to.be.undefined();
// })
// .catch(err => {
// expect(err.message).equal(CoordinatorServerErrorMsg.FillFailed);
// expect(err.approvedOrders).to.be.empty('array');
// expect(err.cancellations).to.be.empty('array');
// const errorBody = err.errors[0];
// expect(errorBody.isError).to.be.true();
// expect(errorBody.status).to.equal(400);
// expect(errorBody.error).to.deep.equal(serverValidationError);
// expect(errorBody.orders).to.deep.equal([signedOrder]);
// expect(errorBody.coordinatorOperator).to.equal(`${coordinatorEndpoint}${coordinatorPort}`);
// const anotherErrorBody = err.errors[1];
// expect(anotherErrorBody.isError).to.be.true();
// expect(anotherErrorBody.status).to.equal(400);
// expect(anotherErrorBody.error).to.deep.equal(serverValidationError);
// expect(anotherErrorBody.orders).to.deep.equal([signedOrderWithDifferentCoordinatorOperator]);
// expect(anotherErrorBody.coordinatorOperator).to.equal(
// `${coordinatorEndpoint}${anotherCoordinatorPort}`,
// );
// done();
// });
// });
// });
// });
// tslint:disable:max-file-line-count

View File

@@ -1,18 +0,0 @@
import { ContractAddresses } from '@0x/contract-addresses';
import { devConstants } from '@0x/dev-utils';
import { runMigrationsOnceAsync } from '@0x/migrations';
import { provider } from './web3_wrapper';
/**
* Configures and runs the migrations exactly once. Any subsequent times this is
* called, it returns the cached addresses.
* @returns The addresses of contracts that were deployed during the migrations.
*/
export async function migrateOnceAsync(): Promise<ContractAddresses> {
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
return runMigrationsOnceAsync(provider, txDefaults);
}