Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
import { Schema, SchemaValidator } from '@0x/json-schemas';
import { Order, SignedOrder, SignedZeroExTransaction, ZeroExTransaction } from '@0x/types';
import * as ethUtil from 'ethereumjs-util';
import { ValidationError as SchemaValidationError } from 'jsonschema';
import * as _ from 'lodash';
import { ValidationError, ValidationErrorCodes, ValidationErrorItem } from './errors';
import { Configs } from './types';
const schemaValidator = new SchemaValidator();
export const utils = {
log: (...args: any[]) => {
// tslint:disable-next-line:no-console
console.log(...args);
},
validateSchema(instance: any, schema: Schema): void {
const validationResult = schemaValidator.validate(instance, schema);
if (_.isEmpty(validationResult.errors)) {
return;
} else {
const validationErrorItems = _.map(
validationResult.errors,
(schemaValidationError: SchemaValidationError) =>
schemaValidationErrorToValidationErrorItem(schemaValidationError),
);
async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise {
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (defaultBlock !== undefined) {
assert.isBlockParam('defaultBlock', defaultBlock);
}
const self = (this as any) as StaticCallProxyContract;
const encodedData = self._strictEncodeArguments('getProxyId()', []);
const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex');
const rawCallResult = await self.evmExecAsync(encodedDataBytes);
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
const abiEncoder = self._lookupAbiEncoder('getProxyId()');
// tslint:disable boolean-naming
const result = abiEncoder.strictDecodeReturnValue(rawCallResult);
async ecSignOrderAsync(
supportedProvider: SupportedProvider,
order: Order,
signerAddress: string,
): Promise {
assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]);
try {
const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(supportedProvider, order, signerAddress);
return signedOrder;
} catch (err) {
// HACK: We are unable to handle specific errors thrown since provider is not an object
// under our control. It could be Metamask Web3, Ethers, or any general RPC provider.
// We check for a user denying the signature request in a way that supports Metamask and
// Coinbase Wallet. Unfortunately for signers with a different error message,
// they will receive two signature requests.
if (err.message.includes('User denied message signature')) {
throw err;
}
const orderHash = await orderHashUtils.getOrderHashAsync(order);
const signatureHex = await signatureUtils.ecSignHashAsync(supportedProvider, orderHash, signerAddress);
const signedOrder = {
...order,
createOrderTypedData: (order: Order): EIP712TypedData => {
assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]);
const normalizedOrder = _.mapValues(order, value => {
return !_.isString(value) ? value.toString() : value;
});
const partialDomain = {
chainId: order.chainId,
verifyingContract: order.exchangeAddress,
};
// Since we are passing in the EXCHANGE_ORDER_SCHEMA
// order paramaters that are not in there get ignored at hashing time
const typedData = eip712Utils.createTypedData(
constants.EXCHANGE_ORDER_SCHEMA.name,
{ Order: constants.EXCHANGE_ORDER_SCHEMA.parameters },
normalizedOrder,
partialDomain,
);
return typedData;
public async marketSellOrdersWithEthAsync(
signedOrders: SignedOrder[],
takerAddress: string,
ethAmount: BigNumber,
signedFeeOrders: SignedOrder[] = [],
feePercentage: number = 0,
feeRecipientAddress: string = constants.NULL_ADDRESS,
orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
): Promise {
// type assertions
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.isBigNumber('ethAmount', ethAmount);
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
assert.isNumber('feePercentage', feePercentage);
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
// other assertions
assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress);
assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress);
// format feePercentage
const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
// lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
// optimize orders
const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
// compile signatures
const signatures = _.map(optimizedMarketOrders, order => order.signature);
public async matchOrdersAsync(
buyOrder: SignedOrder,
sellOrder: SignedOrder,
takerAddress: string,
orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
): Promise {
// type assertions
assert.doesConformToSchema('buyOrder', buyOrder, schemas.signedOrderSchema);
assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase();
// other assertions
if (
sellOrder.makerAssetData !== buyOrder.takerAssetData ||
sellOrder.takerAssetData !== buyOrder.makerAssetData
) {
throw new Error(DutchAuctionWrapperError.AssetDataMismatch);
}
// validate transaction
if (orderTransactionOpts.shouldValidate) {
await this._dutchAuctionContract.matchOrders.callAsync(
buyOrder,
sellOrder,
buyOrder.signature,
public async matchOrdersAsync(
buyOrder: SignedOrder,
sellOrder: SignedOrder,
takerAddress: string,
orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true },
): Promise {
// type assertions
assert.doesConformToSchema('buyOrder', buyOrder, schemas.signedOrderSchema);
assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase();
// other assertions
if (
sellOrder.makerAssetData !== buyOrder.takerAssetData ||
sellOrder.takerAssetData !== buyOrder.makerAssetData
) {
throw new Error(DutchAuctionWrapperError.AssetDataMismatch);
}
// validate transaction
if (orderTransactionOpts.shouldValidate) {
await this._dutchAuctionContract.matchOrders.callAsync(
buyOrder,
sellOrder,
function findOrdersThatCoverAssetFillAmount(
orders: T[],
assetFillAmount: BigNumber,
operation: MarketOperation,
opts?: FindOrdersThatCoverTakerAssetFillAmountOpts | FindOrdersThatCoverMakerAssetFillAmountOpts,
): OrdersAndRemainingTakerFillAmount | OrdersAndRemainingMakerFillAmount {
const variablePrefix = operation === MarketOperation.Buy ? 'Maker' : 'Taker';
assert.doesConformToSchema('orders', orders, schemas.ordersSchema);
assert.isValidBaseUnitAmount('assetFillAmount', assetFillAmount);
// try to get remainingFillableTakerAssetAmounts from opts, if it's not there, use takerAssetAmount values from orders
const remainingFillableAssetAmounts = _.get(
opts,
`remainingFillable${variablePrefix}AssetAmounts`,
_.map(orders, order => (operation === MarketOperation.Buy ? order.makerAssetAmount : order.takerAssetAmount)),
) as BigNumber[];
_.forEach(remainingFillableAssetAmounts, (amount, index) =>
assert.isValidBaseUnitAmount(`remainingFillable${variablePrefix}AssetAmount[${index}]`, amount),
);
assert.assert(
orders.length === remainingFillableAssetAmounts.length,
`Expected orders.length to equal opts.remainingFillable${variablePrefix}AssetAmounts.length`,
);
// try to get slippageBufferAmount from opts, if it's not there, default to 0
const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber;
async ecSignTransactionAsync(
supportedProvider: SupportedProvider,
transaction: ZeroExTransaction,
signerAddress: string,
): Promise {
assert.doesConformToSchema('transaction', transaction, schemas.zeroExTransactionSchema, [schemas.hexSchema]);
try {
const signedTransaction = await signatureUtils.ecSignTypedDataTransactionAsync(
supportedProvider,
transaction,
signerAddress,
);
return signedTransaction;
} catch (err) {
// HACK: We are unable to handle specific errors thrown since provider is not an object
// under our control. It could be Metamask Web3, Ethers, or any general RPC provider.
// We check for a user denying the signature request in a way that supports Metamask and
// Coinbase Wallet. Unfortunately for signers with a different error message,
// they will receive two signature requests.
if (err.message.includes('User denied message signature')) {
throw err;
}
public removeOrder(orderHash: string): void {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const signedOrder = this._orderByOrderHash[orderHash];
if (signedOrder === undefined) {
return; // noop
}
this._dependentOrderHashesTracker.removeFromDependentOrderHashes(signedOrder);
delete this._orderByOrderHash[orderHash];
this._expirationWatcher.removeOrder(orderHash);
delete this._orderStateByOrderHashCache[orderHash];
}
/**