Merge pull request #225 from dekz/feature/track-zrx-movements
Track ZRX Approval and Balance events
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
vx.x.x
|
vx.x.x
|
||||||
------------------------
|
------------------------
|
||||||
* Remove support for Async callback types when used in Subscribe functions
|
* Remove support for Async callback types when used in Subscribe functions
|
||||||
|
* In OrderWatcher subscribe to ZRX Token Transfer and Approval events when maker token is different (#225)
|
||||||
|
|
||||||
v0.25.1 - _November 13, 2017_
|
v0.25.1 - _November 13, 2017_
|
||||||
------------------------
|
------------------------
|
||||||
* Standardise on Cancelled over Canceled
|
* Standardise on Cancelled over Canceled
|
||||||
|
|||||||
@@ -78,24 +78,27 @@ export class OrderStateWatcher {
|
|||||||
* signature is verified.
|
* signature is verified.
|
||||||
* @param signedOrder The order you wish to start watching.
|
* @param signedOrder The order you wish to start watching.
|
||||||
*/
|
*/
|
||||||
public addOrder(signedOrder: SignedOrder): void {
|
public async addOrderAsync(signedOrder: SignedOrder): Promise<void> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker);
|
assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker);
|
||||||
this._orderByOrderHash[orderHash] = signedOrder;
|
this._orderByOrderHash[orderHash] = signedOrder;
|
||||||
this.addToDependentOrderHashes(signedOrder, orderHash);
|
await this.addToDependentOrderHashesAsync(signedOrder, orderHash);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Removes an order from the orderStateWatcher
|
* Removes an order from the orderStateWatcher
|
||||||
* @param orderHash The orderHash of the order you wish to stop watching.
|
* @param orderHash The orderHash of the order you wish to stop watching.
|
||||||
*/
|
*/
|
||||||
public removeOrder(orderHash: string): void {
|
public async removeOrderAsync(orderHash: string): Promise<void> {
|
||||||
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
||||||
const signedOrder = this._orderByOrderHash[orderHash];
|
const signedOrder = this._orderByOrderHash[orderHash];
|
||||||
if (_.isUndefined(signedOrder)) {
|
if (_.isUndefined(signedOrder)) {
|
||||||
return; // noop
|
return; // noop
|
||||||
}
|
}
|
||||||
delete this._orderByOrderHash[orderHash];
|
delete this._orderByOrderHash[orderHash];
|
||||||
|
const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
|
||||||
|
const zrxTokenAddress = await exchange.getZRXTokenAddressAsync();
|
||||||
|
this.removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
|
||||||
this.removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
|
this.removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -210,7 +213,7 @@ export class OrderStateWatcher {
|
|||||||
this._callbackIfExists(orderState);
|
this._callbackIfExists(orderState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string) {
|
private async addToDependentOrderHashesAsync(signedOrder: SignedOrder, orderHash: string): Promise<void> {
|
||||||
if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker])) {
|
if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker])) {
|
||||||
this._dependentOrderHashes[signedOrder.maker] = {};
|
this._dependentOrderHashes[signedOrder.maker] = {};
|
||||||
}
|
}
|
||||||
@@ -218,11 +221,17 @@ export class OrderStateWatcher {
|
|||||||
this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress] = new Set();
|
this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress] = new Set();
|
||||||
}
|
}
|
||||||
this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].add(orderHash);
|
this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].add(orderHash);
|
||||||
|
const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
|
||||||
|
const zrxTokenAddress = await exchange.getZRXTokenAddressAsync();
|
||||||
|
if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress])) {
|
||||||
|
this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress] = new Set();
|
||||||
|
}
|
||||||
|
this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress].add(orderHash);
|
||||||
}
|
}
|
||||||
private removeFromDependentOrderHashes(makerAddress: string, makerTokenAddress: string, orderHash: string) {
|
private removeFromDependentOrderHashes(makerAddress: string, tokenAddress: string, orderHash: string) {
|
||||||
this._dependentOrderHashes[makerAddress][makerTokenAddress].delete(orderHash);
|
this._dependentOrderHashes[makerAddress][tokenAddress].delete(orderHash);
|
||||||
if (this._dependentOrderHashes[makerAddress][makerTokenAddress].size === 0) {
|
if (this._dependentOrderHashes[makerAddress][tokenAddress].size === 0) {
|
||||||
delete this._dependentOrderHashes[makerAddress][makerTokenAddress];
|
delete this._dependentOrderHashes[makerAddress][tokenAddress];
|
||||||
}
|
}
|
||||||
if (_.isEmpty(this._dependentOrderHashes[makerAddress])) {
|
if (_.isEmpty(this._dependentOrderHashes[makerAddress])) {
|
||||||
delete this._dependentOrderHashes[makerAddress];
|
delete this._dependentOrderHashes[makerAddress];
|
||||||
|
|||||||
@@ -73,13 +73,13 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.include({
|
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.include({
|
||||||
[orderHash]: signedOrder,
|
[orderHash]: signedOrder,
|
||||||
});
|
});
|
||||||
let dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
|
let dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
|
||||||
expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
|
expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
|
||||||
zeroEx.orderStateWatcher.removeOrder(orderHash);
|
await zeroEx.orderStateWatcher.removeOrderAsync(orderHash);
|
||||||
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.not.include({
|
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.not.include({
|
||||||
[orderHash]: signedOrder,
|
[orderHash]: signedOrder,
|
||||||
});
|
});
|
||||||
@@ -92,7 +92,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
const nonExistentOrderHash = `0x${orderHash.substr(2).split('').reverse().join('')}`;
|
const nonExistentOrderHash = `0x${orderHash.substr(2).split('').reverse().join('')}`;
|
||||||
zeroEx.orderStateWatcher.removeOrder(nonExistentOrderHash);
|
await zeroEx.orderStateWatcher.removeOrderAsync(nonExistentOrderHash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#subscribe', async () => {
|
describe('#subscribe', async () => {
|
||||||
@@ -109,7 +109,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
zeroEx.orderStateWatcher.unsubscribe();
|
zeroEx.orderStateWatcher.unsubscribe();
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.removeOrder(orderHash);
|
await zeroEx.orderStateWatcher.removeOrderAsync(orderHash);
|
||||||
});
|
});
|
||||||
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -117,7 +117,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
@@ -135,7 +135,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
throw new Error('OrderState callback fired for irrelevant order');
|
throw new Error('OrderState callback fired for irrelevant order');
|
||||||
});
|
});
|
||||||
@@ -156,7 +156,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
@@ -176,7 +176,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
let eventCount = 0;
|
let eventCount = 0;
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
@@ -208,7 +208,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
|
|
||||||
const fillAmountInBaseUnits = new BigNumber(2);
|
const fillAmountInBaseUnits = new BigNumber(2);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
let eventCount = 0;
|
let eventCount = 0;
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
@@ -235,6 +235,22 @@ describe('OrderStateWatcher', () => {
|
|||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
|
it('should trigger the callback when orders backing ZRX allowance changes', (done: DoneCallback) => {
|
||||||
|
(async () => {
|
||||||
|
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
||||||
|
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18);
|
||||||
|
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
|
makerToken.address, takerToken.address, makerFee, takerFee, maker, taker, fillableAmount,
|
||||||
|
taker);
|
||||||
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
zeroEx.orderStateWatcher.subscribe(callback);
|
||||||
|
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
|
||||||
|
})().catch(done);
|
||||||
|
});
|
||||||
describe('remainingFillable(M|T)akerTokenAmount', () => {
|
describe('remainingFillable(M|T)akerTokenAmount', () => {
|
||||||
it('should calculate correct remaining fillable', (done: DoneCallback) => {
|
it('should calculate correct remaining fillable', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -248,7 +264,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
|
const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
|
||||||
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
let eventCount = 0;
|
let eventCount = 0;
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
eventCount++;
|
eventCount++;
|
||||||
@@ -280,7 +296,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||||
|
|
||||||
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), 18);
|
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), 18);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
@@ -305,7 +321,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
|
|
||||||
const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
|
const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
|
||||||
const transferAmount = makerBalance.sub(remainingAmount);
|
const transferAmount = makerBalance.sub(remainingAmount);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
@@ -328,7 +344,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
@@ -350,7 +366,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
@@ -376,7 +392,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
|
|
||||||
const cancelAmountInBaseUnits = new BigNumber(2);
|
const cancelAmountInBaseUnits = new BigNumber(2);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
await zeroEx.orderStateWatcher.addOrderAsync(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.true();
|
expect(orderState.isValid).to.be.true();
|
||||||
|
|||||||
Reference in New Issue
Block a user