aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLeonid <logvinov.leon@gmail.com>2017-06-08 01:01:17 +0800
committerGitHub <noreply@github.com>2017-06-08 01:01:17 +0800
commit834b28bfbe26e0331820d978b5be659b27423528 (patch)
treeaace4130451f80c01fdc5e7da16260e2d70c96e2 /src
parent28d3528e42563f95255cee3bd7f85cc03141522e (diff)
parentca308354880e81425043cd586da6c781013bea9d (diff)
downloaddexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.tar
dexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.tar.gz
dexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.tar.bz2
dexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.tar.lz
dexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.tar.xz
dexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.tar.zst
dexon-sol-tools-834b28bfbe26e0331820d978b5be659b27423528.zip
Merge pull request #42 from 0xProject/addExchangeMethods
Add FillOrKillAsync method & tests
Diffstat (limited to 'src')
-rw-r--r--src/0x.js.ts9
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts67
-rw-r--r--src/types.ts8
3 files changed, 71 insertions, 13 deletions
diff --git a/src/0x.js.ts b/src/0x.js.ts
index 7b53b70ea..8f1178b2a 100644
--- a/src/0x.js.ts
+++ b/src/0x.js.ts
@@ -130,11 +130,12 @@ export class ZeroEx {
* Computes the orderHash for a given order and returns it as a hex encoded string.
*/
public async getOrderHashHexAsync(order: Order|SignedOrder): Promise<string> {
- assert.doesConformToSchema(
- 'order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), orderSchema);
+ assert.doesConformToSchema('order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object),
+ orderSchema);
+
const exchangeContractAddr = await this.getExchangeAddressAsync();
- const hashHex = utils.getOrderHashHex(order, exchangeContractAddr);
- return hashHex;
+ const orderHashHex = utils.getOrderHashHex(order, exchangeContractAddr);
+ return orderHashHex;
}
/**
* Signs an orderHash and returns it's elliptic curve signature
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index 6f62934dc..4f132656e 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -145,6 +145,7 @@ export class ExchangeWrapper extends ContractWrapper {
await this.validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress);
const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(signedOrder);
+
const gas = await exchangeInstance.fill.estimateGas(
orderAddresses,
orderValues,
@@ -173,9 +174,60 @@ export class ExchangeWrapper extends ContractWrapper {
this.throwErrorLogsAsErrors(response.logs);
}
/**
+ * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled,
+ * the fill order is abandoned.
+ */
+ public async fillOrKillOrderAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber,
+ takerAddress: string) {
+ assert.doesConformToSchema('signedOrder',
+ SchemaValidator.convertToJSONSchemaCompatibleObject(signedOrder as object),
+ signedOrderSchema);
+ assert.isBigNumber('fillTakerAmount', fillTakerAmount);
+ await assert.isSenderAddressAsync('takerAddress', takerAddress, this.web3Wrapper);
+
+ const exchangeInstance = await this.getExchangeContractAsync();
+ await this.validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress);
+
+ // Check that fillValue available >= fillTakerAmount
+ const orderHashHex = await this.getOrderHashHexAsync(signedOrder);
+ const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex);
+ const remainingTakerAmount = signedOrder.takerTokenAmount.minus(unavailableTakerAmount);
+ if (remainingTakerAmount < fillTakerAmount) {
+ throw new Error(ExchangeContractErrs.INSUFFICIENT_REMAINING_FILL_AMOUNT);
+ }
+
+ const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(signedOrder);
+
+ const gas = await exchangeInstance.fillOrKill.estimateGas(
+ orderAddresses,
+ orderValues,
+ fillTakerAmount,
+ signedOrder.ecSignature.v,
+ signedOrder.ecSignature.r,
+ signedOrder.ecSignature.s,
+ {
+ from: takerAddress,
+ },
+ );
+ const response: ContractResponse = await exchangeInstance.fillOrKill(
+ orderAddresses,
+ orderValues,
+ fillTakerAmount,
+ signedOrder.ecSignature.v,
+ signedOrder.ecSignature.r,
+ signedOrder.ecSignature.s,
+ {
+ from: takerAddress,
+ gas,
+ },
+ );
+ this.throwErrorLogsAsErrors(response.logs);
+ }
+ /**
* Cancel a given fill amount of an order. Cancellations are cumulative.
*/
- public async cancelOrderAsync(order: Order|SignedOrder, takerTokenCancelAmount: BigNumber.BigNumber): Promise<void> {
+ public async cancelOrderAsync(order: Order|SignedOrder, takerTokenCancelAmount: BigNumber.BigNumber):
+ Promise<void> {
assert.doesConformToSchema('order',
SchemaValidator.convertToJSONSchemaCompatibleObject(order as object),
orderSchema);
@@ -231,11 +283,10 @@ export class ExchangeWrapper extends ContractWrapper {
logEventObj.watch(callback);
this.exchangeLogEventObjs.push(logEventObj);
}
- private async getOrderHashAsync(order: Order|SignedOrder): Promise<string> {
- const [orderAddresses, orderValues] = ExchangeWrapper.getOrderAddressesAndValues(order);
+ private async getOrderHashHexAsync(order: Order|SignedOrder): Promise<string> {
const exchangeInstance = await this.getExchangeContractAsync();
- const orderHash = utils.getOrderHashHex(order, exchangeInstance.address);
- return orderHash;
+ const orderHashHex = utils.getOrderHashHex(order, exchangeInstance.address);
+ return orderHashHex;
}
private async stopWatchingExchangeLogEventsAsync() {
const stopWatchingPromises = _.map(this.exchangeLogEventObjs, logEventObj => {
@@ -273,7 +324,7 @@ export class ExchangeWrapper extends ContractWrapper {
if (takerTokenCancelAmount.eq(0)) {
throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO);
}
- const orderHash = await this.getOrderHashAsync(order);
+ const orderHash = await this.getOrderHashHexAsync(order);
const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash);
if (order.takerTokenAmount.minus(unavailableAmount).eq(0)) {
throw new Error(ExchangeContractErrs.ORDER_ALREADY_CANCELLED_OR_FILLED);
@@ -289,8 +340,8 @@ export class ExchangeWrapper extends ContractWrapper {
* Handling the edge-cases that arise when this happens would require making sure that the user has sufficient
* funds to pay both the fees and the transfer amount. We decided to punt on this for now as the contracts
* will throw for these edge-cases.
- * TODO: Throw errors before calling the smart contract for these edge-cases
- * TODO: in order to minimize the callers gas costs.
+ * TODO: Throw errors before calling the smart contract for these edge-cases in order to minimize
+ * the callers gas costs.
*/
private async validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder: SignedOrder,
fillTakerAmount: BigNumber.BigNumber,
diff --git a/src/types.ts b/src/types.ts
index 5407b0121..cc145dc2e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -74,6 +74,12 @@ export interface ExchangeContract extends ContractInstance {
estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, cancelAmount: BigNumber.BigNumber,
txOpts?: TxOpts) => number;
};
+ fillOrKill: {
+ (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber,
+ v: number, r: string, s: string, txOpts?: TxOpts): ContractResponse;
+ estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber,
+ v: number, r: string, s: string, txOpts?: TxOpts) => number;
+ };
filled: {
call: (orderHash: string) => BigNumber.BigNumber;
};
@@ -139,7 +145,7 @@ export const ExchangeContractErrs = strEnum([
'INSUFFICIENT_MAKER_FEE_BALANCE',
'INSUFFICIENT_MAKER_FEE_ALLOWANCE',
'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER',
-
+ 'INSUFFICIENT_REMAINING_FILL_AMOUNT',
]);
export type ExchangeContractErrs = keyof typeof ExchangeContractErrs;