Skip to content
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

Check existence of the order in the orderbook, and add polledOrderInOrderbook #166

Merged
merged 4 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion src/composable/ConditionalOrder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BigNumber, constants, ethers, utils } from 'ethers'
import { IConditionalOrder } from './generated/ComposableCoW'
import { GPv2Order, IConditionalOrder } from './generated/ComposableCoW'

import { decodeParams, encodeParams } from './utils'
import {
Expand All @@ -14,6 +14,11 @@
PollResultErrors,
} from './types'
import { getComposableCow, getComposableCowInterface } from './contracts'
import { OrderBookApi, UID } from 'src/order-book'
import { computeOrderUid } from 'src/utils'
import { Order } from '@cowprotocol/contracts'

const orderBookCache: Record<string, OrderBookApi> = {}

/**
* An abstract base class from which all conditional orders should inherit.
Expand Down Expand Up @@ -281,6 +286,43 @@
[]
)

let orderBookApi = orderBookCache[chainId]
if (!orderBookApi) {
orderBookApi = new OrderBookApi({ chainId })
orderBookCache[chainId] = orderBookApi
}

// TODO: Derive orderId from the order data
/*
{
name: "Gnosis Protocol",
version: "v2",
chainId: chainId,
verifyingContract: GPV2SETTLEMENT,
}
*/

const orderUid = await computeOrderUid(chainId, owner, order as Order)
anxolin marked this conversation as resolved.
Show resolved Hide resolved

// Check if the order is already in the order book
const isOrderInOrderbook = await orderBookApi
.getOrder(orderUid)
.then(() => true)
.catch(() => false)

// Let the concrete Conditional Order decide about the poll result (in the case the order is already in the orderbook)
if (isOrderInOrderbook) {
const pollResult = await this.polledOrderInOrderbook(orderUid, order, params)
if (pollResult) {
return pollResult
}

return {
result: PollResultCode.TRY_NEXT_BLOCK,
reason: 'Order already in orderbook',
}
}

return {
result: PollResultCode.SUCCESS,
order,
Expand Down Expand Up @@ -330,6 +372,20 @@
*/
protected abstract pollValidate(params: PollParams): Promise<PollResultErrors | undefined>

/**
* This method lets the concrete conditional order decide what to do if the order yielded in the polling has been already created.
*
* The concrete conditional order will have a chance to schedule the next poll.
* For example, a TWAP order that has the current part already in the orderbook, can signal that the next poll should be done at the time of the next part.
*
* @param params
*/
protected abstract polledOrderInOrderbook(
anxolin marked this conversation as resolved.
Show resolved Hide resolved
orderUid: UID,
order: GPv2Order.DataStructOutput,
params: PollParams
): Promise<PollResultErrors | undefined>

/**
* Convert the struct that the contract expect as an encoded `staticInput` into a friendly data object modelling the smart order.
*
Expand Down Expand Up @@ -364,7 +420,7 @@
s: string,
handler: string,
orderDataTypes: string[],
callback: (d: any, salt: string) => T

Check warning on line 423 in src/composable/ConditionalOrder.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
): T {
try {
// First, decode the `IConditionalOrder.Params` struct
Expand All @@ -378,7 +434,7 @@

// Create a new instance of the class
return callback(d, salt)
} catch (e: any) {

Check warning on line 437 in src/composable/ConditionalOrder.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
if (e.message === 'HandlerMismatch') {
throw e
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/composable/orderTypes/Twap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
PollResultErrors,
} from '../types'
import { encodeParams, formatEpoch, getBlockInfo, isValidAbi } from '../utils'
import { GPv2Order } from '../generated/ComposableCoW'

// The type of Conditional Order
const TWAP_ORDER_TYPE = 'twap'
Expand Down Expand Up @@ -350,6 +351,14 @@
return undefined
}

protected async polledOrderInOrderbook(
_orderUid: string,

Check warning on line 355 in src/composable/orderTypes/Twap.ts

View workflow job for this annotation

GitHub Actions / eslint

'_orderUid' is defined but never used
_order: GPv2Order.DataStructOutput,

Check warning on line 356 in src/composable/orderTypes/Twap.ts

View workflow job for this annotation

GitHub Actions / eslint

'_order' is defined but never used
_params: PollParams

Check warning on line 357 in src/composable/orderTypes/Twap.ts

View workflow job for this annotation

GitHub Actions / eslint

'_params' is defined but never used
): Promise<PollResultErrors | undefined> {
return undefined
anxolin marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Serialize the TWAP order into it's ABI-encoded form.
* @returns {string} The ABI-encoded TWAP order.
Expand Down
10 changes: 9 additions & 1 deletion src/composable/orderTypes/test/TestConditionalOrder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GPv2Order } from 'src/composable/generated/ComposableCoW'
import { ConditionalOrder } from '../../ConditionalOrder'
import { IsValidResult, PollResultErrors } from '../../types'
import { IsValidResult, PollParams, PollResultErrors } from '../../types'
import { encodeParams } from '../../utils'

export const DEFAULT_ORDER_PARAMS: TestConditionalOrderParams = {
Expand Down Expand Up @@ -51,6 +52,13 @@ export class TestConditionalOrder extends ConditionalOrder<string, string> {
protected async pollValidate(): Promise<PollResultErrors | undefined> {
return undefined
}
protected async polledOrderInOrderbook(
_orderUid: string,
_order: GPv2Order.DataStructOutput,
_params: PollParams
): Promise<PollResultErrors | undefined> {
return undefined
}

isValid(): IsValidResult {
return { isValid: true }
Expand Down
10 changes: 10 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { Order } from '@cowprotocol/contracts'
import type { SupportedChainId } from './common'
import { OrderSigningUtils } from './order-signing'

export async function computeOrderUid(chainId: SupportedChainId, owner: string, order: Order): Promise<string> {
const { computeOrderUid: _computeOrderUid } = await import('@cowprotocol/contracts')
const domain = await OrderSigningUtils.getDomain(chainId)

return _computeOrderUid(domain, order, owner)
}
Loading