From 3ff6ed38f4a7c1f6db28b705e4d015ca2553b79d Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Thu, 24 Aug 2023 18:51:46 +0100 Subject: [PATCH 1/3] Add factory --- package.json | 2 +- src/composable/ConditionalOrder.spec.ts | 2 +- src/composable/ConditionalOrder.ts | 2 +- src/composable/ConditionalOrderFactory.ts | 24 +++++++++++++++++ src/composable/Multiplexer.spec.ts | 4 +-- src/composable/Multiplexer.ts | 17 +++++++----- src/composable/index.ts | 2 ++ .../{types => orderTypes}/Twap.spec.ts | 0 src/composable/{types => orderTypes}/Twap.ts | 27 +++++++++++++++---- src/composable/orderTypes/index.ts | 8 ++++++ src/composable/types.ts | 4 +-- src/composable/types/index.ts | 1 - src/composable/utils.spec.ts | 21 +++++++++++++-- 13 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 src/composable/ConditionalOrderFactory.ts rename src/composable/{types => orderTypes}/Twap.spec.ts (100%) rename src/composable/{types => orderTypes}/Twap.ts (95%) create mode 100644 src/composable/orderTypes/index.ts delete mode 100644 src/composable/types/index.ts diff --git a/package.json b/package.json index 8c111e97..0b2d8e2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "3.0.0-rc.1", + "version": "3.0.0-rc.2", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" diff --git a/src/composable/ConditionalOrder.spec.ts b/src/composable/ConditionalOrder.spec.ts index 02ec4963..e49e0629 100644 --- a/src/composable/ConditionalOrder.spec.ts +++ b/src/composable/ConditionalOrder.spec.ts @@ -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 => { diff --git a/src/composable/ConditionalOrder.ts b/src/composable/ConditionalOrder.ts index 6036002b..5d0b58c7 100644 --- a/src/composable/ConditionalOrder.ts +++ b/src/composable/ConditionalOrder.ts @@ -11,7 +11,7 @@ import { PollResultCode, PollResultErrors, } from './types' -import { SupportedChainId } from 'src/common' +import { SupportedChainId } from '../common' import { getComposableCow, getComposableCowInterface } from './contracts' /** diff --git a/src/composable/ConditionalOrderFactory.ts b/src/composable/ConditionalOrderFactory.ts new file mode 100644 index 00000000..64c825d0 --- /dev/null +++ b/src/composable/ConditionalOrderFactory.ts @@ -0,0 +1,24 @@ +import { type ConditionalOrder } from './ConditionalOrder' +import { ConditionalOrderParams } from './types' + +export type FromParams = (params: ConditionalOrderParams) => ConditionalOrder +export type ConditionalOrderRegistry = Record> + +export class ConditionalOrderFactory { + public knownOrderTypes + + constructor(registry: ConditionalOrderRegistry) { + this.knownOrderTypes = registry + } + + public fromParams(params: ConditionalOrderParams): ConditionalOrder | undefined { + const { handler } = params + + const factory = this.knownOrderTypes[handler] + if (!factory) { + return undefined + } + + return factory(params) + } +} diff --git a/src/composable/Multiplexer.spec.ts b/src/composable/Multiplexer.spec.ts index 288fd4fa..631b5e87 100644 --- a/src/composable/Multiplexer.spec.ts +++ b/src/composable/Multiplexer.spec.ts @@ -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' diff --git a/src/composable/Multiplexer.ts b/src/composable/Multiplexer.ts index d0e037c0..159973ef 100644 --- a/src/composable/Multiplexer.ts +++ b/src/composable/Multiplexer.ts @@ -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> +export type Orders = Record> /** * Multiplexer for conditional orders - using `ComposableCoW`! @@ -24,7 +24,7 @@ export type Orders = Record> * - Support for passing an optional upload function to upload the proofs to a decentralized storage network */ export class Multiplexer { - static orderTypeRegistry: Record ConditionalOrder> = {} + static orderTypeRegistry: Record ConditionalOrder> = {} public chain: SupportedChainId public location: ProofLocation @@ -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 + const conditionalOrder = v as ConditionalOrder return { ...conditionalOrder, orderType: conditionalOrder.orderType, @@ -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(id: string, updater: (order: ConditionalOrder, ctx?: string) => ConditionalOrder): void { + update( + id: string, + updater: (order: ConditionalOrder, ctx?: string) => ConditionalOrder + ): 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 @@ -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 { + getById(id: string): ConditionalOrder { return this.orders[id] } @@ -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 { + getByIndex(i: number): ConditionalOrder { return this.orders[this.orderIds[i]] } @@ -431,7 +434,7 @@ export class Multiplexer { */ public static registerOrderType( orderType: string, - conditionalOrderClass: new (...args: any[]) => ConditionalOrder + conditionalOrderClass: new (...args: unknown[]) => ConditionalOrder ) { Multiplexer.orderTypeRegistry[orderType] = conditionalOrderClass } diff --git a/src/composable/index.ts b/src/composable/index.ts index eb61b1e1..ea7e7f48 100644 --- a/src/composable/index.ts +++ b/src/composable/index.ts @@ -2,3 +2,5 @@ export * from './types' export * from './utils' export * from './ConditionalOrder' export * from './Multiplexer' +export * from './ConditionalOrderFactory' +export * from './orderTypes' diff --git a/src/composable/types/Twap.spec.ts b/src/composable/orderTypes/Twap.spec.ts similarity index 100% rename from src/composable/types/Twap.spec.ts rename to src/composable/orderTypes/Twap.spec.ts diff --git a/src/composable/types/Twap.ts b/src/composable/orderTypes/Twap.ts similarity index 95% rename from src/composable/types/Twap.ts rename to src/composable/orderTypes/Twap.ts index ff4303ae..4075dedd 100644 --- a/src/composable/types/Twap.ts +++ b/src/composable/orderTypes/Twap.ts @@ -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' @@ -179,6 +186,16 @@ export class Twap extends ConditionalOrder { 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 { + const twap = Twap.deserialize(encodeParams(params)) + return twap + } + /** * Enforces that TWAPs will commence at the beginning of a block by use of the * `CurrentBlockTimestampFactory` contract to provide the current block timestamp @@ -283,12 +300,12 @@ export class Twap extends ConditionalOrder { /** * 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) => diff --git a/src/composable/orderTypes/index.ts b/src/composable/orderTypes/index.ts new file mode 100644 index 00000000..af888762 --- /dev/null +++ b/src/composable/orderTypes/index.ts @@ -0,0 +1,8 @@ +import { ConditionalOrderRegistry } from '../ConditionalOrderFactory' +import { TWAP_ADDRESS, Twap } from './Twap' +export * from './Twap' + +export const DEFAULT_CONDITIONAL_ORDER_REGSTRY: ConditionalOrderRegistry = { + // Register of all known order types + [TWAP_ADDRESS]: (params) => Twap.fromParams(params), +} diff --git a/src/composable/types.ts b/src/composable/types.ts index 956703bf..8edf7e0c 100644 --- a/src/composable/types.ts +++ b/src/composable/types.ts @@ -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[] } } @@ -104,7 +104,7 @@ export interface PollResultSuccess { export interface PollResultUnexpectedError { readonly result: PollResultCode.UNEXPECTED_ERROR - readonly error: any + readonly error: unknown } export interface PollResultTryNextBlock { diff --git a/src/composable/types/index.ts b/src/composable/types/index.ts deleted file mode 100644 index bda8c540..00000000 --- a/src/composable/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Twap' diff --git a/src/composable/utils.spec.ts b/src/composable/utils.spec.ts index bbe36876..6d2577f8 100644 --- a/src/composable/utils.spec.ts +++ b/src/composable/utils.spec.ts @@ -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)', From 32e7421d3d33f9563539f60be2315450e3a490fd Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Thu, 24 Aug 2023 20:00:46 +0100 Subject: [PATCH 2/3] Set rc.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b2d8e2e..9fcac0a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/cow-sdk", - "version": "3.0.0-rc.2", + "version": "3.0.0-rc.3", "license": "(MIT OR Apache-2.0)", "files": [ "/dist" From 355507632fb4a3d9de265086daceaeb7c243e410 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Tue, 29 Aug 2023 15:22:26 +0100 Subject: [PATCH 3/3] Improvements from Leandro Co-authored-by: Leandro --- src/composable/orderTypes/Twap.ts | 3 +-- src/composable/orderTypes/index.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/composable/orderTypes/Twap.ts b/src/composable/orderTypes/Twap.ts index 4075dedd..03fa9559 100644 --- a/src/composable/orderTypes/Twap.ts +++ b/src/composable/orderTypes/Twap.ts @@ -192,8 +192,7 @@ export class Twap extends ConditionalOrder { * @returns An instance of the TWAP order. */ static fromParams(params: ConditionalOrderParams): Twap { - const twap = Twap.deserialize(encodeParams(params)) - return twap + return Twap.deserialize(encodeParams(params)) } /** diff --git a/src/composable/orderTypes/index.ts b/src/composable/orderTypes/index.ts index af888762..943fbaeb 100644 --- a/src/composable/orderTypes/index.ts +++ b/src/composable/orderTypes/index.ts @@ -3,6 +3,6 @@ import { TWAP_ADDRESS, Twap } from './Twap' export * from './Twap' export const DEFAULT_CONDITIONAL_ORDER_REGSTRY: ConditionalOrderRegistry = { - // Register of all known order types + // Registry of all known order types [TWAP_ADDRESS]: (params) => Twap.fromParams(params), }