-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle Expired TWAP and not started TWAP (#153)
* Get block info * Read from the cabinet the start date ans do custom twap validation * Add descriptive message * Fix condition check * Handle expiration * Leave todo for handling next part at a specific time * Handle specific polling for TWAP * Update version * Fix typos * Create OwnerContext type * Add isSingleOrder flag * Get cabinet also for merkle root orders * Decode cabinet and verify its value * Add offchain and proof to poll params
- Loading branch information
Showing
6 changed files
with
136 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { BigNumber, constants, providers } from 'ethers' | ||
import { BigNumber, constants, utils } from 'ethers' | ||
|
||
import { ConditionalOrder } from '../ConditionalOrder' | ||
import { | ||
|
@@ -7,10 +7,12 @@ import { | |
ContextFactory, | ||
IsNotValid, | ||
IsValid, | ||
OwnerContext, | ||
PollParams, | ||
PollResultCode, | ||
PollResultErrors, | ||
} from '../types' | ||
import { encodeParams, isValidAbi } from '../utils' | ||
import { SupportedChainId } from '../../common' | ||
import { encodeParams, formatEpoch, getBlockInfo, isValidAbi } from '../utils' | ||
|
||
// The type of Conditional Order | ||
const TWAP_ORDER_TYPE = 'twap' | ||
|
@@ -161,6 +163,8 @@ const DEFAULT_DURATION_OF_PART: DurationOfPart = { durationType: DurationType.AU | |
* @author mfw78 <[email protected]> | ||
*/ | ||
export class Twap extends ConditionalOrder<TwapData, TwapStruct> { | ||
isSingleOrder = true | ||
|
||
/** | ||
* @see {@link ConditionalOrder.constructor} | ||
* @throws If the TWAP order is invalid. | ||
|
@@ -263,6 +267,23 @@ export class Twap extends ConditionalOrder<TwapData, TwapStruct> { | |
return error ? { isValid: false, reason: error } : { isValid: true } | ||
} | ||
|
||
private async startTimestamp(params: OwnerContext): Promise<number> { | ||
const { startTime } = this.data | ||
|
||
if (startTime?.startType === StartTimeValue.AT_EPOC) { | ||
return startTime.epoch.toNumber() | ||
} | ||
|
||
const cabinet = await this.cabinet(params) | ||
const cabinetEpoc = utils.defaultAbiCoder.decode(['uint256'], cabinet)[0] | ||
|
||
if (cabinetEpoc === 0) { | ||
throw new Error('Cabinet is not set. Required for TWAP orders that start at mining time.') | ||
} | ||
|
||
return parseInt(cabinet, 16) | ||
} | ||
|
||
/** | ||
* Checks if the owner authorized the conditional order. | ||
* | ||
|
@@ -271,13 +292,44 @@ export class Twap extends ConditionalOrder<TwapData, TwapStruct> { | |
* @param provider An RPC provider for the chain. | ||
* @returns true if the owner authorized the order, false otherwise. | ||
*/ | ||
protected async pollValidate( | ||
_owner: string, | ||
_chain: SupportedChainId, | ||
_provider: providers.Provider | ||
): Promise<PollResultErrors | undefined> { | ||
// TODO: Do not check again expired order | ||
// TODO: Calculate the next part start time, signal to not check again until then | ||
protected async pollValidate(params: PollParams): Promise<PollResultErrors | undefined> { | ||
const { blockInfo = await getBlockInfo(params.provider) } = params | ||
const { blockTimestamp } = blockInfo | ||
const { numberOfParts, timeBetweenParts } = this.data | ||
|
||
const startTimestamp = await this.startTimestamp(params) | ||
|
||
if (startTimestamp > blockTimestamp) { | ||
// The start time hasn't started | ||
return { | ||
result: PollResultCode.TRY_AT_EPOCH, | ||
epoch: startTimestamp, | ||
reason: `TWAP hasn't started yet. Starts at ${startTimestamp} (${formatEpoch(startTimestamp)})`, | ||
} | ||
} | ||
|
||
const expirationTimestamp = startTimestamp + numberOfParts.mul(timeBetweenParts).toNumber() | ||
if (blockTimestamp >= expirationTimestamp) { | ||
// The order has expired | ||
return { | ||
result: PollResultCode.DONT_TRY_AGAIN, | ||
reason: `TWAP has expired. Expired at ${expirationTimestamp} (${formatEpoch(expirationTimestamp)})`, | ||
} | ||
} | ||
|
||
// TODO: Do not check between parts | ||
// - 1. Check whats the order parameters for the current partNumber | ||
// - 2. Derive discrete orderUid | ||
// - 3. Verify if this is already created in the API | ||
// - 4. If so, we know we should return | ||
// return { | ||
// result: PollResultCode.TRY_AT_EPOCH, | ||
// epoch: nextPartStartTime, | ||
// reason: `Current active TWAP part is already created. The next one doesn't start until ${nextPartStartTime} (${formatEpoch(nextPartStartTime)})`, | ||
// } | ||
// // Get current part number | ||
// const partNumber = Math.floor(blockTimestamp - startTimestamp / timeBetweenParts.toNumber()) | ||
|
||
return undefined | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters