Skip to content

Commit

Permalink
Add Conditional Order factory (#151)
Browse files Browse the repository at this point in the history
* Add factory

* Set rc.3

* Improvements from Leandro

Co-authored-by: Leandro <[email protected]>

---------

Co-authored-by: Leandro <[email protected]>
  • Loading branch information
anxolin and alfetopito authored Aug 29, 2023
1 parent e77585b commit 34fbd9a
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cowprotocol/cow-sdk",
"version": "3.0.0-rc.1",
"version": "3.0.0-rc.3",
"license": "(MIT OR Apache-2.0)",
"files": [
"/dist"
Expand Down
2 changes: 1 addition & 1 deletion src/composable/ConditionalOrder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ConditionalOrder } from './ConditionalOrder'
import { IsValidResult, PollResultErrors } from './types'
import { Twap } from './types/Twap'
import { Twap } from './orderTypes/Twap'
import { encodeParams } from './utils'

const TWAP_SERIALIZED = (salt?: string, handler?: string): string => {
Expand Down
2 changes: 1 addition & 1 deletion src/composable/ConditionalOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
PollResultCode,
PollResultErrors,
} from './types'
import { SupportedChainId } from 'src/common'
import { SupportedChainId } from '../common'
import { getComposableCow, getComposableCowInterface } from './contracts'

/**
Expand Down
24 changes: 24 additions & 0 deletions src/composable/ConditionalOrderFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type ConditionalOrder } from './ConditionalOrder'
import { ConditionalOrderParams } from './types'

export type FromParams<D, S> = (params: ConditionalOrderParams) => ConditionalOrder<D, S>
export type ConditionalOrderRegistry = Record<string, FromParams<unknown, unknown>>

export class ConditionalOrderFactory {
public knownOrderTypes

constructor(registry: ConditionalOrderRegistry) {
this.knownOrderTypes = registry
}

public fromParams(params: ConditionalOrderParams): ConditionalOrder<unknown, unknown> | undefined {
const { handler } = params

const factory = this.knownOrderTypes[handler]
if (!factory) {
return undefined
}

return factory(params)
}
}
4 changes: 2 additions & 2 deletions src/composable/Multiplexer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Multiplexer, Orders } from './Multiplexer'
import { SupportedChainId } from '../common'
import { ProofLocation } from './types'
import { Twap } from './types/Twap'
import { TWAP_PARAMS_TEST, generateRandomTWAPData } from './types/Twap.spec'
import { Twap } from './orderTypes/Twap'
import { TWAP_PARAMS_TEST, generateRandomTWAPData } from './orderTypes/Twap.spec'
import { getComposableCowInterface } from './contracts'
import { BigNumber } from 'ethers'

Expand Down
17 changes: 10 additions & 7 deletions src/composable/Multiplexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const CONDITIONAL_ORDER_LEAF_ABI = ['address', 'bytes32', 'bytes']

const PAYLOAD_EMITTED_ABI = ['tuple(bytes32[] proof, tuple(address handler, bytes32 salt, bytes staticInput) params)[]']

export type Orders = Record<string, ConditionalOrder<any, any>>
export type Orders = Record<string, ConditionalOrder<unknown, unknown>>

/**
* Multiplexer for conditional orders - using `ComposableCoW`!
Expand All @@ -24,7 +24,7 @@ export type Orders = Record<string, ConditionalOrder<any, any>>
* - Support for passing an optional upload function to upload the proofs to a decentralized storage network
*/
export class Multiplexer {
static orderTypeRegistry: Record<string, new (...args: any[]) => ConditionalOrder<any, any>> = {}
static orderTypeRegistry: Record<string, new (...args: unknown[]) => ConditionalOrder<unknown, unknown>> = {}

public chain: SupportedChainId
public location: ProofLocation
Expand Down Expand Up @@ -148,7 +148,7 @@ export class Multiplexer {
// filter out the merkle tree
if (k === 'tree') return undefined
if (typeof v === 'object' && v !== null && 'orderType' in v) {
const conditionalOrder = v as ConditionalOrder<any, any>
const conditionalOrder = v as ConditionalOrder<unknown, unknown>
return {
...conditionalOrder,
orderType: conditionalOrder.orderType,
Expand Down Expand Up @@ -186,7 +186,10 @@ export class Multiplexer {
* @param id The id of the `ConditionalOrder` to update.
* @param updater A function that takes the existing `ConditionalOrder` and context, returning an updated `ConditionalOrder`.
*/
update<T, P>(id: string, updater: (order: ConditionalOrder<T, P>, ctx?: string) => ConditionalOrder<T, P>): void {
update(
id: string,
updater: (order: ConditionalOrder<unknown, unknown>, ctx?: string) => ConditionalOrder<unknown, unknown>
): void {
// copy the existing order and update it, given the existing context (if any)
const order = updater(this.orders[id], this.ctx)
// delete the existing order
Expand All @@ -204,7 +207,7 @@ export class Multiplexer {
* @param id The `id` of the `ConditionalOrder` to retrieve.
* @returns A `ConditionalOrder` with the given `id`.
*/
getById(id: string): ConditionalOrder<any, any> {
getById(id: string): ConditionalOrder<unknown, unknown> {
return this.orders[id]
}

Expand All @@ -213,7 +216,7 @@ export class Multiplexer {
* @param i The index of the `ConditionalOrder` to retrieve.
* @returns A `ConditionalOrder` at the given index.
*/
getByIndex(i: number): ConditionalOrder<any, any> {
getByIndex(i: number): ConditionalOrder<unknown, unknown> {
return this.orders[this.orderIds[i]]
}

Expand Down Expand Up @@ -431,7 +434,7 @@ export class Multiplexer {
*/
public static registerOrderType(
orderType: string,
conditionalOrderClass: new (...args: any[]) => ConditionalOrder<any, any>
conditionalOrderClass: new (...args: unknown[]) => ConditionalOrder<unknown, unknown>
) {
Multiplexer.orderTypeRegistry[orderType] = conditionalOrderClass
}
Expand Down
2 changes: 2 additions & 0 deletions src/composable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from './types'
export * from './utils'
export * from './ConditionalOrder'
export * from './Multiplexer'
export * from './ConditionalOrderFactory'
export * from './orderTypes'
File renamed without changes.
26 changes: 21 additions & 5 deletions src/composable/types/Twap.ts → src/composable/orderTypes/Twap.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { BigNumber, constants, providers } from 'ethers'

import { ConditionalOrder } from '../ConditionalOrder'
import { ConditionalOrderArguments, ContextFactory, IsNotValid, IsValid, PollResultErrors } from '../types'
import {
ConditionalOrderArguments,
ConditionalOrderParams,
ContextFactory,
IsNotValid,
IsValid,
PollResultErrors,
} from '../types'
import { encodeParams, isValidAbi } from '../utils'
import { SupportedChainId } from 'src/common'
import { SupportedChainId } from '../../common'

// The type of Conditional Order
const TWAP_ORDER_TYPE = 'twap'
Expand Down Expand Up @@ -179,6 +186,15 @@ export class Twap extends ConditionalOrder<TwapData, TwapStruct> {
return new Twap({ handler: TWAP_ADDRESS, data })
}

/**
* Create a TWAP order with sound defaults.
* @param data The TWAP order parameters in a more user-friendly format.
* @returns An instance of the TWAP order.
*/
static fromParams(params: ConditionalOrderParams): Twap {
return Twap.deserialize(encodeParams(params))
}

/**
* Enforces that TWAPs will commence at the beginning of a block by use of the
* `CurrentBlockTimestampFactory` contract to provide the current block timestamp
Expand Down Expand Up @@ -283,12 +299,12 @@ export class Twap extends ConditionalOrder<TwapData, TwapStruct> {

/**
* Deserialize a TWAP order from it's ABI-encoded form.
* @param {string} s ABI-encoded TWAP order to deserialize.
* @param {string} twapSerialized ABI-encoded TWAP order to deserialize.
* @returns A deserialized TWAP order.
*/
static deserialize(s: string): Twap {
static deserialize(twapSerialized: string): Twap {
return super.deserializeHelper(
s,
twapSerialized,
TWAP_ADDRESS,
TWAP_STRUCT_ABI,
(struct: TwapStruct, salt: string) =>
Expand Down
8 changes: 8 additions & 0 deletions src/composable/orderTypes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ConditionalOrderRegistry } from '../ConditionalOrderFactory'
import { TWAP_ADDRESS, Twap } from './Twap'
export * from './Twap'

export const DEFAULT_CONDITIONAL_ORDER_REGSTRY: ConditionalOrderRegistry = {
// Registry of all known order types
[TWAP_ADDRESS]: (params) => Twap.fromParams(params),
}
4 changes: 2 additions & 2 deletions src/composable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type ContextFactory = {
address: string
// Any arguments that will be passed to the `IValueFactory` to resolve the context.
factoryArgs?: {
args: any[]
args: unknown[]
argsType: string[]
}
}
Expand Down Expand Up @@ -104,7 +104,7 @@ export interface PollResultSuccess {

export interface PollResultUnexpectedError {
readonly result: PollResultCode.UNEXPECTED_ERROR
readonly error: any
readonly error: unknown
}

export interface PollResultTryNextBlock {
Expand Down
1 change: 0 additions & 1 deletion src/composable/types/index.ts

This file was deleted.

21 changes: 19 additions & 2 deletions src/composable/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import { decodeParams, encodeParams, isValidAbi } from './utils'
import { TwapStruct, transformDataToStruct } from './types/Twap'
import { TWAP_PARAMS_TEST } from './types/twap.spec'
import { DurationType, StartTimeValue, TwapData, TwapStruct, transformDataToStruct } from './orderTypes/Twap'
import { BigNumber, utils } from 'ethers'

export const TWAP_PARAMS_TEST: TwapData = {
sellToken: '0x6810e776880C02933D47DB1b9fc05908e5386b96',
buyToken: '0xDAE5F1590db13E3B40423B5b5c5fbf175515910b',
receiver: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
sellAmount: utils.parseEther('1'),
buyAmount: utils.parseEther('1'),
timeBetweenParts: BigNumber.from(60 * 60),
numberOfParts: BigNumber.from(10),
durationOfPart: {
durationType: DurationType.AUTO,
},
startTime: {
startType: StartTimeValue.AT_MINING_TIME,
},
appData: '0xd51f28edffcaaa76be4a22f6375ad289272c037f3cc072345676e88d92ced8b5',
}

const TWAP_STRUCT_ABI = [
'tuple(address sellToken, address buyToken, address receiver, uint256 partSellAmount, uint256 minPartLimit, uint256 t0, uint256 n, uint256 t, uint256 span, bytes32 appData)',
Expand Down

0 comments on commit 34fbd9a

Please sign in to comment.