Skip to content

Commit 416793e

Browse files
authored
feat(UniswapX): Add expected amounts to DutchV3 (#347)
1 parent d07ba97 commit 416793e

File tree

2 files changed

+105
-5
lines changed

2 files changed

+105
-5
lines changed

sdks/uniswapx-sdk/src/trade/V3DutchOrderTrade.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,68 @@ describe("V3DutchOrderTrade", () => {
211211
expect(ethOutputTrade.outputAmount.currency).toEqual(Ether.onChain(1));
212212
});
213213
});
214+
215+
describe("Expected amounts", () => {
216+
const expectedAmounts = {
217+
expectedAmountIn: "800",
218+
expectedAmountOut: "900",
219+
};
220+
221+
const tradeWithExpectedAmounts = new V3DutchOrderTrade<Currency, Currency, TradeType>({
222+
currencyIn: USDC,
223+
currenciesOut: [DAI],
224+
orderInfo,
225+
tradeType: TradeType.EXACT_INPUT,
226+
expectedAmounts,
227+
});
228+
229+
it("uses expectedAmountIn when provided", () => {
230+
expect(tradeWithExpectedAmounts.inputAmount.quotient.toString()).toEqual(
231+
expectedAmounts.expectedAmountIn
232+
);
233+
});
234+
235+
it("uses expectedAmountOut when provided", () => {
236+
expect(tradeWithExpectedAmounts.outputAmount.quotient.toString()).toEqual(
237+
expectedAmounts.expectedAmountOut
238+
);
239+
});
240+
241+
it("falls back to order amounts when expectedAmounts is not provided", () => {
242+
expect(trade.inputAmount.quotient.toString()).toEqual(
243+
orderInfo.input.startAmount.toString()
244+
);
245+
expect(trade.outputAmount.quotient.toString()).toEqual(
246+
NON_FEE_OUTPUT_AMOUNT.toString()
247+
);
248+
});
249+
250+
it("throws when accessing expectedAmountIn that wasn't provided", () => {
251+
const tradeWithoutExpected = new V3DutchOrderTrade<Currency, Currency, TradeType>({
252+
currencyIn: USDC,
253+
currenciesOut: [DAI],
254+
orderInfo,
255+
tradeType: TradeType.EXACT_INPUT,
256+
});
257+
258+
// Using private method through any to test error case
259+
expect(() => {
260+
(tradeWithoutExpected as any).getExpectedAmountIn();
261+
}).toThrow("expectedAmountIn not set");
262+
});
263+
264+
it("throws when accessing expectedAmountOut that wasn't provided", () => {
265+
const tradeWithoutExpected = new V3DutchOrderTrade<Currency, Currency, TradeType>({
266+
currencyIn: USDC,
267+
currenciesOut: [DAI],
268+
orderInfo,
269+
tradeType: TradeType.EXACT_INPUT,
270+
});
271+
272+
// Using private method through any to test error case
273+
expect(() => {
274+
(tradeWithoutExpected as any).getExpectedAmountOut();
275+
}).toThrow("expectedAmountOut not set");
276+
});
277+
});
214278
});

sdks/uniswapx-sdk/src/trade/V3DutchOrderTrade.ts

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export class V3DutchOrderTrade<
1313
> {
1414
public readonly tradeType: TTradeType
1515
public readonly order: UnsignedV3DutchOrder
16+
public readonly expectedAmounts: {
17+
expectedAmountIn: string;
18+
expectedAmountOut: string;
19+
} | undefined;
1620

1721
private _inputAmount: CurrencyAmount<TInput> | undefined
1822
private _outputAmounts: CurrencyAmount<TOutput>[] | undefined
@@ -25,15 +29,21 @@ export class V3DutchOrderTrade<
2529
currenciesOut,
2630
orderInfo,
2731
tradeType,
32+
expectedAmounts,
2833
}: {
2934
currencyIn: TInput
3035
currenciesOut: TOutput[]
3136
orderInfo: UnsignedV3DutchOrderInfo
3237
tradeType: TTradeType
38+
expectedAmounts?: {
39+
expectedAmountIn: string;
40+
expectedAmountOut: string;
41+
}
3342
}) {
3443
this._currencyIn = currencyIn
3544
this._currenciesOut = currenciesOut
3645
this.tradeType = tradeType
46+
this.expectedAmounts = expectedAmounts;
3747

3848
// Assuming not cross-chain
3949
this.order = new UnsignedV3DutchOrder(orderInfo, currencyIn.chainId)
@@ -42,10 +52,12 @@ export class V3DutchOrderTrade<
4252
public get inputAmount(): CurrencyAmount<TInput> {
4353
if (this._inputAmount) return this._inputAmount
4454

45-
const amount = CurrencyAmount.fromRawAmount(
46-
this._currencyIn,
47-
this.order.info.input.startAmount.toString()
48-
)
55+
const amount = this.expectedAmounts?.expectedAmountIn
56+
? this.getExpectedAmountIn()
57+
: CurrencyAmount.fromRawAmount(
58+
this._currencyIn,
59+
this.order.info.input.startAmount.toString()
60+
)
4961
this._inputAmount = amount
5062
return amount
5163
}
@@ -72,7 +84,9 @@ export class V3DutchOrderTrade<
7284

7385
// Same assumption as V2 that there is only one non-fee output at a time, and it exists at index 0
7486
public get outputAmount(): CurrencyAmount<TOutput> {
75-
return this.outputAmounts[0];
87+
return this.expectedAmounts?.expectedAmountOut
88+
? this.getExpectedAmountOut()
89+
: this.outputAmounts[0];
7690
}
7791

7892
public minimumAmountOut(): CurrencyAmount<TOutput> {
@@ -123,4 +137,26 @@ export class V3DutchOrderTrade<
123137
this.minimumAmountOut().quotient
124138
);
125139
}
140+
141+
private getExpectedAmountIn(): CurrencyAmount<TInput> {
142+
if (!this.expectedAmounts?.expectedAmountIn) {
143+
throw new Error("expectedAmountIn not set");
144+
}
145+
146+
return CurrencyAmount.fromRawAmount(
147+
this._currencyIn,
148+
this.expectedAmounts.expectedAmountIn
149+
);
150+
}
151+
152+
private getExpectedAmountOut(): CurrencyAmount<TOutput> {
153+
if (!this.expectedAmounts?.expectedAmountOut) {
154+
throw new Error("expectedAmountOut not set");
155+
}
156+
157+
return CurrencyAmount.fromRawAmount(
158+
this._currenciesOut[0],
159+
this.expectedAmounts.expectedAmountOut
160+
);
161+
}
126162
}

0 commit comments

Comments
 (0)