aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts66
-rw-r--r--src/types.ts7
2 files changed, 73 insertions, 0 deletions
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index 72ae0d07e..524ebdc0f 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -176,6 +176,72 @@ export class ExchangeWrapper extends ContractWrapper {
this.throwErrorLogsAsErrors(response.logs);
}
/**
+ * Sequentially and atomically fills signedOrders up to takerTokenFillAmount.
+ * If fill amount is reached - it succeeds and doesn't fill the rest of the orders.
+ * If fill amount is not reached - it just fills all the orders.
+ */
+ public async fillOrderUpToAsync(signedOrders: SignedOrder[], takerTokenFillAmount: BigNumber.BigNumber,
+ shouldCheckTransfer: boolean, takerAddress: string): Promise<void> {
+ const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
+ assert.assert(_.uniq(takerTokenAddresses).length === 1,
+ ExchangeContractErrs.MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO);
+ assert.isBigNumber('takerTokenFillAmount', takerTokenFillAmount);
+ assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
+ await assert.isSenderAddressAsync('takerAddress', takerAddress, this.web3Wrapper);
+ _.forEach(signedOrders,
+ async (signedOrder: SignedOrder, i: number) => {
+ assert.doesConformToSchema(`signedOrder[${i}]`,
+ SchemaValidator.convertToJSONSchemaCompatibleObject(signedOrder as object),
+ signedOrderSchema);
+ await this.validateFillOrderAndThrowIfInvalidAsync(
+ signedOrder, takerTokenFillAmount, takerAddress);
+ });
+ if (_.isEmpty(signedOrders)) {
+ return; // no-op
+ }
+
+ const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => {
+ return [
+ ...ExchangeWrapper.getOrderAddressesAndValues(signedOrder),
+ signedOrder.ecSignature.v,
+ signedOrder.ecSignature.r,
+ signedOrder.ecSignature.s,
+ ];
+ });
+ // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
+ const [orderAddressesArray, orderValuesArray, vArray, rArray, sArray] = _.unzip<any>(
+ orderAddressesValuesAndSignatureArray,
+ );
+
+ const exchangeInstance = await this.getExchangeContractAsync();
+ const gas = await exchangeInstance.fillUpTo.estimateGas(
+ orderAddressesArray,
+ orderValuesArray,
+ takerTokenFillAmount,
+ shouldCheckTransfer,
+ vArray,
+ rArray,
+ sArray,
+ {
+ from: takerAddress,
+ },
+ );
+ const response: ContractResponse = await exchangeInstance.fillUpTo(
+ orderAddressesArray,
+ orderValuesArray,
+ takerTokenFillAmount,
+ shouldCheckTransfer,
+ vArray,
+ rArray,
+ sArray,
+ {
+ from: takerAddress,
+ gas,
+ },
+ );
+ this.throwErrorLogsAsErrors(response.logs);
+ }
+ /**
* Batch version of fillOrderAsync.
* Executes multiple fills atomically in a single transaction.
* If shouldCheckTransfer is set to true, it will continue filling subsequent orders even when earlier ones fail.
diff --git a/src/types.ts b/src/types.ts
index edd7f2d33..2dabfaa3c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -74,6 +74,12 @@ export interface ExchangeContract extends ContractInstance {
estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[], fillAmounts: BigNumber.BigNumber[],
shouldCheckTransfer: boolean, v: number[], r: string[], s: string[], txOpts?: TxOpts) => number;
};
+ fillUpTo: {
+ (orderAddresses: OrderAddresses[], orderValues: OrderValues[], fillAmount: BigNumber.BigNumber,
+ shouldCheckTransfer: boolean, v: number[], r: string[], s: string[], txOpts?: TxOpts): ContractResponse;
+ estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[], fillAmount: BigNumber.BigNumber,
+ shouldCheckTransfer: boolean, v: number[], r: string[], s: string[], txOpts?: TxOpts) => number;
+ };
cancel: {
(orderAddresses: OrderAddresses, orderValues: OrderValues, cancelAmount: BigNumber.BigNumber,
txOpts?: TxOpts): ContractResponse;
@@ -159,6 +165,7 @@ export const ExchangeContractErrs = strEnum([
'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER',
'MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH',
'INSUFFICIENT_REMAINING_FILL_AMOUNT',
+ 'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO',
]);
export type ExchangeContractErrs = keyof typeof ExchangeContractErrs;