-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve TWAP order mapping with activeOrderUid
#1785
Conversation
Pull Request Test Coverage Report for Build 10112332202Details
💛 - Coveralls |
unknown
if getting part orders failsactiveOrderUid
@@ -680,6 +786,7 @@ describe('TwapOrderMapper', () => { | |||
}); | |||
|
|||
it('should map the TWAP order if source apps are restricted and a part order fullAppData matches any of the allowed apps', async () => { | |||
configurationService.set('swaps.maxNumberOfParts', 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test began failing without this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's weird, I can't replicate the failure, maybe it's a flaky test for some reason. Or maybe the value is set on another test as the configuration is not cleaned between the tests if I'm not wrong. Anyway, I'm good with setting this explictly here.
if (args.partOrders) { | ||
const order = args.partOrders.find((order) => order.uid === orderUid); | ||
if (order) { | ||
return order.status; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'm misunderstanding this, but if you just return the order status, wouldn't that be wrong for "fulfilled" orders? If the status is fulfilled for one part, it doesn't mean that this applies to the whole TWAP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic regarding status generation is different as of #1785 (comment) which should now solve this.
const order = await this.swapsRepository.getOrder(args.chainId, orderUid); | ||
// If the active order is fulfilled, the next one may not yet exist | ||
// and fetching it would fail so we assume it's open | ||
if (args.activeOrderUid && order.status === OrderStatus.Fulfilled) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whenever this order exists we have to return the total twap order status as Open.
Even if the activePart is still open or even if it got cancelled (as it is possible to cancel a single part without cancelling the whole order)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per discussion, we now assume open
, fullfilled
or cancelled
depending on the existince of an active/final order part as of dfea594.
|
||
// If the order was created, the TWAP is either open or fulfilled depending | ||
// on whether the order part is active | ||
return args.activeOrderUid ? OrderStatus.Open : OrderStatus.Fulfilled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is one more edge case we missed when we talked about this:
If the activeOrderUid is the last part.
activeOrderUid === this.gpv2OrderHelper.computeOrderUid({
chainId: args.chainId,
owner: args.safeAddress,
order: args.twapParts.slice(-1)[0], // Last part's order
});
In that case we could return Fulfilled
if the order is already in a final state (fulfilled, cancelled).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 686505d.
}); | ||
|
||
// If active order is final one, it's fulfilled as it exists | ||
if (args.activeOrderUid === finalOrderUid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we still have to fetch in order to know that it exists.
twapParts
and activeOrderUid
are both just computed here. So if the last twap would be active this will always be true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted in f20a158.
|
||
// If the order exists, the TWAP is either open or fulfilled depending | ||
// on whether the order is active | ||
return args.activeOrderUid ? OrderStatus.Open : OrderStatus.Fulfilled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could remove the above check (where I commented) and instead do something like this here:
return args.activeOrderUid ? OrderStatus.Open : OrderStatus.Fulfilled; | |
return args.activeOrderUid ? args.activeOrderUid === finalOrderUid ? OrderStatus.Fulfilled : OrderStatus.Open : OrderStatus.Fulfilled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted in f20a158.
@@ -841,6 +948,7 @@ describe('TwapOrderMapper', () => { | |||
}); | |||
|
|||
expect(result).toEqual({ | |||
activeOrderUid: null, | |||
buyAmount: '51576509680023161648', | |||
buyToken: { | |||
address: buyToken.address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add these (or similar) testcases for the Order Status mapping?
- Cancelled Order with 3 parts where only the first part exists and the second part is currently active.
- Cancelled ORder with 3 parts where only the first 2 parts exist and the last part is currently active (This would be a case that should currently fail)
- Fulfilled Order with 3 parts where the last part is currently active and the repository returns fulfilled for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in f20a158.
mockSwapsRepository.getOrder.mockImplementation( | ||
async (_chainId: string, orderUid: string) => { | ||
if (orderUid === part2.uid) { | ||
return Promise.resolve(part2); | ||
} | ||
return Promise.reject(new NotFoundException()); | ||
}, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I encountered issues in the new test cases that were due to incorrectly calculated order UIDs. As such, I adjusted these mocks to be more specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks correct to me :) Thanks for going through those edge cases 🥇
@@ -680,6 +786,7 @@ describe('TwapOrderMapper', () => { | |||
}); | |||
|
|||
it('should map the TWAP order if source apps are restricted and a part order fullAppData matches any of the allowed apps', async () => { | |||
configurationService.set('swaps.maxNumberOfParts', 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's weird, I can't replicate the failure, maybe it's a flaky test for some reason. Or maybe the value is set on another test as the configuration is not cleaned between the tests if I'm not wrong. Anyway, I'm good with setting this explictly here.
Adds a new `activeOrderUid` to the `TwapOrderTransactionInfo`, calculating the status from it: - Add `activeOrderUid` to `TwapOrderTransactionInfo`. - Fetch status relative to `activeOrderUid`. - Add appropriate test coverage.
Summary
In order to cancel a TWAP, the current order UID needs to be referenced. As we calculate each of these, it makes sense to return it as part of the transaction info (as well as at the request of the client).
This adds a new
activeOrderUid
to theTwapOrderTransactionInfo
. On top of this, as we were previously calculating the status based on the initial 10 parts of a TWAP, or the last for those with >10, we now fetch the status from the active part. This fixes the issue whereby large part TWAPs were returning the incorrect status - final parts are not created meaning they would always throw.Changes
activeOrderUid
toTwapOrderTransactionInfo
.activeOrderUid
.