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

Test poll happy path and not authorized #159

Merged
merged 5 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
119 changes: 97 additions & 22 deletions src/composable/ConditionalOrder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Twap } from './orderTypes/Twap'

import { getComposableCow } from './contracts'
import { constants } from 'ethers'
import { OwnerContext, PollParams, PollResultCode } from './types'
import { BuyTokenDestination, OrderKind, SellTokenSource } from '../order-book/generated'

jest.mock('./contracts')
const mockGetComposableCow = getComposableCow as jest.MockedFunction<typeof getComposableCow>
Expand All @@ -30,19 +32,32 @@ const TWAP_SERIALIZED = (salt?: string, handler?: string): string => {
)
}

const SINGLE_ORDER = new TestConditionalOrder(
'0x910d00a310f7Dc5B29FE73458F47f519be547D3d',
'0x9379a0bf532ff9a66ffde940f94b1a025d6f18803054c1aef52dc94b15255bbe',
'0x',
true
)
const createOrder = (isSingleOrder = true) =>
new TestConditionalOrder(
'0x910d00a310f7Dc5B29FE73458F47f519be547D3d',
'0x9379a0bf532ff9a66ffde940f94b1a025d6f18803054c1aef52dc94b15255bbe',
'0x',
isSingleOrder
)

const MERKLE_ROOT_ORDER = new TestConditionalOrder(
'0x910d00a310f7Dc5B29FE73458F47f519be547D3d',
'0x9379a0bf532ff9a66ffde940f94b1a025d6f18803054c1aef52dc94b15255bbe',
'0x',
false
)
const OWNER = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
const SINGLE_ORDER = createOrder()
const MERKLE_ROOT_ORDER = createOrder(false)
const DISCRETE_ORDER = {
sellToken: '0x6810e776880c02933d47db1b9fc05908e5386b96',
buyToken: '0x6810e776880c02933d47db1b9fc05908e5386b96',
receiver: '0x6810e776880c02933d47db1b9fc05908e5386b96',
sellAmount: '1234567890',
buyAmount: '1234567890',
validTo: 0,
appData: '0x0000000000000000000000000000000000000000000000000000000000000000',
partiallyFillable: true,
sellTokenBalance: SellTokenSource.ERC20,
buyTokenBalance: BuyTokenDestination.ERC20,
from: '0x6810e776880c02933d47db1b9fc05908e5386b96',
kind: OrderKind.BUY,
class: 'market',
}

describe('Constructor', () => {
test('Create TestConditionalOrder', () => {
Expand Down Expand Up @@ -102,21 +117,16 @@ describe('Compute orderUid', () => {
})

test('Derive OrderId from leaf data', () => {
const order = new TestConditionalOrder(
'0x910d00a310f7Dc5B29FE73458F47f519be547D3d',
'0x9379a0bf532ff9a66ffde940f94b1a025d6f18803054c1aef52dc94b15255bbe'
)
expect(ConditionalOrder.leafToId(order.leaf)).toEqual(
expect(ConditionalOrder.leafToId(SINGLE_ORDER.leaf)).toEqual(
'0x88ca0698d8c5500b31015d84fa0166272e1812320d9af8b60e29ae00153363b3'
)
})
})

describe('cabinet', () => {
const owner = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
describe('Cabinet', () => {
const cabinetValue = '000000000000000000000000000000000000000000000000000000064f0b353'
const mockCabinet = jest.fn()
const param = { owner } as any
const param = { owner: OWNER } as OwnerContext
beforeEach(() => {
jest.resetAllMocks()

Expand All @@ -140,7 +150,7 @@ describe('cabinet', () => {
expect(mockCabinet.mock.calls).toHaveLength(1)

// THEN: we expect the params to be the owner and the order id
expect(mockCabinet.mock.calls[0]).toEqual([owner, SINGLE_ORDER.id])
expect(mockCabinet.mock.calls[0]).toEqual([OWNER, SINGLE_ORDER.id])
})

test('Merkle Root orders call the contract with the 0x0 as the ctx', () => {
Expand All @@ -153,6 +163,71 @@ describe('cabinet', () => {
expect(mockCabinet.mock.calls).toHaveLength(1)

// THEN: we expect the params to be the owner and 0x0
expect(mockCabinet.mock.calls[0]).toEqual([owner, constants.HashZero])
expect(mockCabinet.mock.calls[0]).toEqual([OWNER, constants.HashZero])
})
})

describe('Poll Single Orders', () => {
const mockSingleOrders = jest.fn()
const mockGetTradeableOrderWithSignature = jest.fn()
const param = { owner: OWNER, chainId: 1, provider: {} } as PollParams

const signature = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
beforeEach(() => {
jest.resetAllMocks()

mockGetComposableCow.mockReturnValue({
callStatic: {
singleOrders: mockSingleOrders,
},
getTradeableOrderWithSignature: mockGetTradeableOrderWithSignature,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any)
})

test.only('[SUCCESS] Happy path', async () => {
// GIVEN: An order that is authorised
mockSingleOrders.mockReturnValue(true)

// GIVEN: And a getTradeableOrderWithSignature that doesn't revert
mockGetTradeableOrderWithSignature.mockReturnValue([DISCRETE_ORDER, signature])

// WHEN: we poll
const pollResult = await SINGLE_ORDER.poll(param)

// THEN: we expect a CALL to getTradeableOrderWithSignature with the owner, params, off-chain input, and no-proof
expect(mockGetTradeableOrderWithSignature.mock.calls).toHaveLength(1)
expect(mockGetTradeableOrderWithSignature.mock.calls[0]).toEqual([
OWNER,
SINGLE_ORDER.leaf,
SINGLE_ORDER.offChainInput,
[],
])

// THEN: We expect a SUCCESS result, which returns the order and the signature
expect(pollResult).toEqual({
result: PollResultCode.SUCCESS,
order: DISCRETE_ORDER,
signature,
})
})

test.only('[DONT_TRY_AGAIN] Not authorised', async () => {
// GIVEN: An order that is not authorised
mockSingleOrders.mockReturnValue(false)

// GIVEN: And a getTradeableOrderWithSignature that doesn't revert
mockGetTradeableOrderWithSignature.mockReturnValue([DISCRETE_ORDER, signature])

// WHEN: we poll
const pollResult = await SINGLE_ORDER.poll(param)

// THEN: We expect an error. We shouldn't try again
pollResult.result === PollResultCode.UNEXPECTED_ERROR && console.error(pollResult.error)
expect(pollResult).toEqual({
result: PollResultCode.DONT_TRY_AGAIN,
reason:
'NotAuthorised: Order 0x88ca0698d8c5500b31015d84fa0166272e1812320d9af8b60e29ae00153363b3 is not authorised for 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 on chain 1',
})
})
})
6 changes: 3 additions & 3 deletions src/composable/ConditionalOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,8 @@ export abstract class ConditionalOrder<D, S> {
}

// Check if the owner authorised the order
const isAuthorized = await this.isAuthorized(params)
if (!isAuthorized) {
const isAuthorised = await this.isAuthorised(params)
if (!isAuthorised) {
return {
result: PollResultCode.DONT_TRY_AGAIN,
reason: `NotAuthorised: Order ${this.id} is not authorised for ${owner} on chain ${chainId}`,
Expand Down Expand Up @@ -300,7 +300,7 @@ export abstract class ConditionalOrder<D, S> {
* @param params owner context, to be able to check if the order is authorised
* @returns true if the owner authorised the order, false otherwise.
*/
public isAuthorized(params: OwnerContext): Promise<boolean> {
public isAuthorised(params: OwnerContext): Promise<boolean> {
anxolin marked this conversation as resolved.
Show resolved Hide resolved
const { chainId, owner, provider } = params
const composableCow = getComposableCow(chainId, provider)
return composableCow.callStatic.singleOrders(owner, this.id)
Expand Down
2 changes: 1 addition & 1 deletion src/composable/Multiplexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export class Multiplexer {
chain: SupportedChainId,
provider: providers.Provider,
offChainInputFn?: (owner: string, params: ConditionalOrderParams) => Promise<string>
): Promise<[GPv2Order.DataStructOutput, string]> {
): Promise<[GPv2Order.DataStruct, string]> {
const composableCow = getComposableCow(chain, provider)

const offChainInput = offChainInputFn ? await offChainInputFn(owner, p.params) : '0x'
Expand Down
6 changes: 3 additions & 3 deletions src/composable/orderTypes/test/TestConditionalOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ export class TestConditionalOrder extends ConditionalOrder<string, string> {
return params
}

protected pollValidate(): Promise<PollResultErrors | undefined> {
throw new Error('Method not implemented.')
protected async pollValidate(): Promise<PollResultErrors | undefined> {
return undefined
}

isValid(): IsValidResult {
throw new Error('Method not implemented.')
return { isValid: true }
}
serialize(): string {
return encodeParams(this.leaf)
Expand Down
6 changes: 3 additions & 3 deletions src/composable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export type OwnerContext = {
}

export type PollParams = OwnerContext & {
offchainInput: string
proof: string[]
offchainInput?: string
proof?: string[]

/**
* If present, it can be used for custom conditional order validations. If not present, the orders will need to get the block info themselves
Expand Down Expand Up @@ -121,7 +121,7 @@ export enum PollResultCode {
}
export interface PollResultSuccess {
readonly result: PollResultCode.SUCCESS
readonly order: GPv2Order.DataStructOutput
readonly order: GPv2Order.DataStruct
readonly signature: string
}

Expand Down
Loading