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

feat: Support DutchV3 Orders #384

Merged
merged 11 commits into from
Dec 2, 2024
1 change: 1 addition & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export const POST_ORDER_ERROR_REASON = {

export const WEBHOOK_TIMEOUT_MS = 500;
export const NOTIFICATION_TIMEOUT_MS = 10;
export const V3_BLOCK_BUFFER = 4;
35 changes: 26 additions & 9 deletions lib/entities/HardQuoteRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TradeType } from '@uniswap/sdk-core';
import { UnsignedV2DutchOrder } from '@uniswap/uniswapx-sdk';
import { OrderType, UnsignedV2DutchOrder, UnsignedV3DutchOrder, V3DutchOrderBuilder } from '@uniswap/uniswapx-sdk';
import { BigNumber, ethers, utils } from 'ethers';
import { v4 as uuidv4 } from 'uuid';

Expand All @@ -8,19 +8,25 @@ import { HardQuoteRequestBody } from '../handlers/hard-quote';
import { ProtocolVersion } from '../providers';

export class HardQuoteRequest {
public order: UnsignedV2DutchOrder;
public order: UnsignedV2DutchOrder | UnsignedV3DutchOrder;
private data: HardQuoteRequestBody;

public static fromHardRequestBody(body: HardQuoteRequestBody): HardQuoteRequest {
return new HardQuoteRequest(body);
public static fromHardRequestBody(body: HardQuoteRequestBody, orderType: OrderType): HardQuoteRequest {
return new HardQuoteRequest(body, orderType);
}

constructor(_data: HardQuoteRequestBody) {
constructor(_data: HardQuoteRequestBody, orderType: OrderType) {
this.data = {
..._data,
requestId: _data.quoteId ?? uuidv4(),
};
this.order = UnsignedV2DutchOrder.parse(_data.encodedInnerOrder, _data.tokenInChainId);
if (orderType === OrderType.Dutch_V2) {
this.order = UnsignedV2DutchOrder.parse(_data.encodedInnerOrder, _data.tokenInChainId);
} else if (orderType === OrderType.Dutch_V3) {
this.order = UnsignedV3DutchOrder.parse(_data.encodedInnerOrder, _data.tokenInChainId);
} else {
throw new Error('Unsupported order type');
}
}

public toCleanJSON(): QuoteRequestDataJSON {
Expand Down Expand Up @@ -110,9 +116,20 @@ export class HardQuoteRequest {
}

public get type(): TradeType {
return this.order.info.input.startAmount.eq(this.order.info.input.endAmount)
? TradeType.EXACT_INPUT
: TradeType.EXACT_OUTPUT;
if (this.order instanceof UnsignedV2DutchOrder) {
return this.order.info.input.startAmount.eq(this.order.info.input.endAmount)
? TradeType.EXACT_INPUT
: TradeType.EXACT_OUTPUT
}
else if (this.order instanceof UnsignedV3DutchOrder) {
const startAmount = this.order.info.input.startAmount;
return startAmount.eq(V3DutchOrderBuilder.getMinAmountOut(startAmount, this.order.info.input.curve.relativeAmounts))
alanhwu marked this conversation as resolved.
Show resolved Hide resolved
? TradeType.EXACT_INPUT
: TradeType.EXACT_OUTPUT
}
else {
throw new Error('Unsupported order type');
}
}

public get numOutputs(): number {
Expand Down
44 changes: 4 additions & 40 deletions lib/entities/HardQuoteResponse.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { CosignedV2DutchOrder } from '@uniswap/uniswapx-sdk';
import { BigNumber } from 'ethers';
import { CosignedV2DutchOrder, CosignedV3DutchOrder } from '@uniswap/uniswapx-sdk';
import { v4 as uuidv4 } from 'uuid';

import { HardQuoteRequest } from '.';
import { HardQuoteResponseData } from '../handlers/hard-quote/schema';
import { currentTimestampInMs, timestampInMstoSeconds } from '../util/time';

// data class for hard quote response helpers and conversions
export class HardQuoteResponse {
export abstract class HardQuoteResponse<T extends CosignedV2DutchOrder | CosignedV3DutchOrder> {
public createdAt: string;

constructor(
public request: HardQuoteRequest,
public order: CosignedV2DutchOrder,
public order: T,
public createdAtMs = currentTimestampInMs()
) {
this.createdAt = timestampInMstoSeconds(parseInt(this.createdAtMs));
Expand All @@ -29,23 +28,7 @@ export class HardQuoteResponse {
};
}

public toLog() {
return {
quoteId: this.quoteId,
requestId: this.requestId,
tokenInChainId: this.chainId,
tokenOutChainId: this.chainId,
tokenIn: this.tokenIn,
amountIn: this.amountIn.toString(),
tokenOut: this.tokenOut,
amountOut: this.amountOut.toString(),
swapper: this.swapper,
filler: this.filler,
orderHash: this.order.hash(),
createdAt: this.createdAt,
createdAtMs: this.createdAtMs,
};
}
public abstract toLog(): any;

public get quoteId(): string {
return this.request.quoteId ?? uuidv4();
Expand All @@ -67,25 +50,6 @@ export class HardQuoteResponse {
return this.request.tokenIn;
}

public get amountOut(): BigNumber {
const resolved = this.order.resolve({
timestamp: this.order.info.cosignerData.decayStartTime,
});
let amount = BigNumber.from(0);
for (const output of resolved.outputs) {
amount = amount.add(output.amount);
}

return amount;
}

public get amountIn(): BigNumber {
const resolved = this.order.resolve({
timestamp: this.order.info.cosignerData.decayStartTime,
});
return resolved.input.amount;
}

public get tokenOut(): string {
return this.request.tokenOut;
}
Expand Down
42 changes: 42 additions & 0 deletions lib/entities/V2HardQuoteResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { BigNumber } from "ethers";
import { HardQuoteResponse } from "./HardQuoteResponse";
import { CosignedV2DutchOrder } from "@uniswap/uniswapx-sdk";

export class V2HardQuoteResponse extends HardQuoteResponse<CosignedV2DutchOrder> {
public toLog() {
return {
quoteId: this.quoteId,
requestId: this.requestId,
tokenInChainId: this.chainId,
tokenOutChainId: this.chainId,
tokenIn: this.tokenIn,
amountIn: this.amountIn.toString(),
tokenOut: this.tokenOut,
amountOut: this.amountOut.toString(),
swapper: this.swapper,
filler: this.filler,
orderHash: this.order.hash(),
createdAt: this.createdAt,
createdAtMs: this.createdAtMs,
};
}

public get amountOut(): BigNumber {
alanhwu marked this conversation as resolved.
Show resolved Hide resolved
const resolved = this.order.resolve({
timestamp: this.order.info.cosignerData.decayStartTime,
});
let amount = BigNumber.from(0);
for (const output of resolved.outputs) {
amount = amount.add(output.amount);
}

return amount;
}

public get amountIn(): BigNumber {
const resolved = this.order.resolve({
timestamp: this.order.info.cosignerData.decayStartTime,
});
return resolved.input.amount;
}
}
48 changes: 48 additions & 0 deletions lib/entities/V3HardQuoteResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { CosignedV3DutchOrder } from "@uniswap/uniswapx-sdk";
import { HardQuoteResponse } from "./HardQuoteResponse";

export class V3HardQuoteResponse extends HardQuoteResponse<CosignedV3DutchOrder> {
public toLog() {
return {
quoteId: this.quoteId,
requestId: this.requestId,
tokenInChainId: this.chainId,
tokenOutChainId: this.chainId,
tokenIn: this.tokenIn,
input: this.input,
tokenOut: this.tokenOut,
outputs: this.outputs,
swapper: this.swapper,
filler: this.filler,
orderHash: this.order.hash(),
createdAt: this.createdAt,
createdAtMs: this.createdAtMs,
};
}

get input() {
const input = this.order.info.input;
const relativeAmounts = input.curve.relativeAmounts.map((amount) => amount.toString());

return {
...input,
curve: {
...input.curve,
relativeAmounts,
},
}
}

get outputs() {
const processedOutputs = this.order.info.outputs.map((output) => {
return {
...output,
curve: {
...output.curve,
relativeAmounts: output.curve.relativeAmounts.map((amount) => amount.toString()),
}
}
});
return processedOutputs;
}
}
Loading
Loading