Skip to content
Open
Show file tree
Hide file tree
Changes from 12 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
18 changes: 2 additions & 16 deletions src/examples/delta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@ async function simpleDeltaFlow() {
const tx = await deltaSDK.approveTokenForDelta(amount, DAI_TOKEN);
await tx.wait();

const slippagePercent = 0.5;
const destAmountAfterSlippage = BigInt(
// get rid of exponential notation

+(+deltaPrice.destAmount * (1 - slippagePercent / 100)).toFixed(0)
// get rid of decimals
).toString(10);

const deltaAuction = await deltaSDK.submitDeltaOrder({
deltaPrice,
owner: account,
Expand All @@ -67,7 +59,7 @@ async function simpleDeltaFlow() {
srcToken: DAI_TOKEN,
destToken: USDC_TOKEN,
srcAmount: amount,
destAmount: destAmountAfterSlippage, // minimum acceptable destAmount
slippage: 50, // 50 bps = 0.5% slippage, destAmount auto-computed from deltaPrice
});

// poll if necessary
Expand All @@ -92,12 +84,6 @@ async function manualDeltaFlow() {
const tx = await deltaSDK.approveTokenForDelta(amount, DAI_TOKEN);
await tx.wait();

const slippagePercent = 0.5;
const destAmountAfterSlippage = (
+deltaPrice.destAmount *
(1 - slippagePercent / 100)
).toString(10);

const signableOrderData = await deltaSDK.buildDeltaOrder({
deltaPrice,
owner: account,
Expand All @@ -106,7 +92,7 @@ async function manualDeltaFlow() {
srcToken: DAI_TOKEN,
destToken: USDC_TOKEN,
srcAmount: amount,
destAmount: destAmountAfterSlippage, // minimum acceptable destAmount
slippage: 50, // 50 bps = 0.5% slippage, destAmount auto-computed from deltaPrice
});

const signature = await deltaSDK.signDeltaOrder(signableOrderData);
Expand Down
103 changes: 93 additions & 10 deletions src/methods/delta/buildDeltaOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type { SignableDeltaOrderData } from './helpers/buildDeltaOrderData';

export type SwapSideUnion = EnumerateLiteral<typeof SwapSide>;

export type BuildDeltaOrderDataParams = {
type BuildDeltaOrderDataParamsBase = {
/** @description The address of the order owner */
owner: string;
/** @description The address of the order beneficiary */
Expand All @@ -28,10 +28,6 @@ export type BuildDeltaOrderDataParams = {
srcToken: string; // lowercase
/** @description The address of the dest token. For Crosschain Order - destination token on the destination chain */
destToken: string; // lowercase
/** @description The amount of src token to swap */
srcAmount: string; // wei
/** @description The minimum amount of dest token to receive */
destAmount: string; // wei, deltaPrice.destAmount - slippage
/** @description The deadline for the order */
deadline?: number; // seconds
/** @description The nonce of the order */
Expand Down Expand Up @@ -68,12 +64,44 @@ export type BuildDeltaOrderDataParams = {
/** @description A boolean indicating whether the surplus should be capped. True by default */
capSurplus?: boolean;

/** @description The side of the order. Default is SELL */
side?: SwapSideUnion;
/** @description Metadata for the order, hex string */
metadata?: string;
};

/** @description SELL with slippage: srcAmount provided, destAmount auto-computed from deltaPrice.destAmount */
type DeltaAmountsSellSlippage = {
/** @description Slippage in basis points (bps). 10000 = 100%, 50 = 0.5% */
slippage: number;
/** @description The amount of src token to swap */
srcAmount: string;
destAmount?: never;
/** @description The side of the order */
side?: 'SELL';
};
/** @description BUY with slippage: destAmount provided, srcAmount auto-computed from deltaPrice.srcAmount */
type DeltaAmountsBuySlippage = {
/** @description Slippage in basis points (bps). 10000 = 100%, 50 = 0.5% */
slippage: number;
/** @description The minimum amount of dest token to receive */
destAmount: string;
srcAmount?: never;
/** @description The side of the order */
side?: 'BUY';
};
/** @description Explicit amounts, no slippage (backward-compatible) */
type DeltaAmountsExplicit = {
slippage?: never;
/** @description The amount of src token to swap */
srcAmount: string;
/** @description The minimum amount of dest token to receive */
destAmount: string;
/** @description The side of the order. Default is SELL */
side?: SwapSideUnion;
};

export type BuildDeltaOrderDataParams = BuildDeltaOrderDataParamsBase &
(DeltaAmountsSellSlippage | DeltaAmountsBuySlippage | DeltaAmountsExplicit);

type BuildDeltaOrder = (
buildOrderParams: BuildDeltaOrderDataParams,
requestParams?: RequestParameters
Expand Down Expand Up @@ -138,7 +166,40 @@ export const constructBuildDeltaOrder = (
partnerFeeBps = partnerFeeBps ?? 0;
partnerTakesSurplus = partnerTakesSurplus ?? false;

const swapSide = options.side ?? SwapSide.SELL;
// Resolve srcAmount, destAmount and side.
// When slippage is used, side is inferred from which amount is present.
let srcAmount: string;
let destAmount: string;

const swapSide: SwapSideUnion =
options.slippage !== undefined
? options.srcAmount
? SwapSide.SELL
: SwapSide.BUY
: options.side ?? SwapSide.SELL;

if (options.slippage !== undefined) {
if (options.srcAmount !== undefined) {
// SELL with slippage: destAmount auto-computed
srcAmount = options.srcAmount;
destAmount = applySlippage(
options.deltaPrice.destAmount,
options.slippage,
false
);
} else {
// BUY with slippage: srcAmount auto-computed
destAmount = options.destAmount;
srcAmount = applySlippage(
options.deltaPrice.srcAmount,
options.slippage,
true
);
}
} else {
srcAmount = options.srcAmount;
destAmount = options.destAmount;
}

const expectedAmount =
swapSide === SwapSide.SELL
Expand All @@ -152,8 +213,8 @@ export const constructBuildDeltaOrder = (
// for some cases of WETH->ETH crosschain swaps, the destToken is changed to WETH or ETH,
// this is already reflected in deltaPrice
destToken: options.deltaPrice.destToken,
srcAmount: options.srcAmount,
destAmount: options.destAmount,
srcAmount,
destAmount,
expectedAmount,
deadline: options.deadline,
nonce: options.nonce?.toString(10),
Expand All @@ -179,3 +240,25 @@ export const constructBuildDeltaOrder = (
buildDeltaOrder,
};
};

function applySlippage(
amount: string,
slippageBps: number,
increase: boolean
): string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually prefer object as input, more readable that way

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated 8f66540

if (
!Number.isInteger(slippageBps) ||
slippageBps < 0 ||
slippageBps >= 10_000
) {
throw new Error('slippageBps must be an integer between 0 and 10_000');
}

const BPS_BASE = 10_000n;
const amt = BigInt(amount);
const bps = BigInt(slippageBps);

return increase
? ((amt * (BPS_BASE + bps)) / BPS_BASE).toString(10)
: ((amt * (BPS_BASE - bps)) / BPS_BASE).toString(10);
}
2 changes: 1 addition & 1 deletion tests/__snapshots__/limitOrders.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ exports[`Limit Orders Build_Swap+LO_Tx 1`] = `
"maxImpactReached": false,
"network": 1,
"partner": "anon",
"partnerFee": 0,
"partnerFee": NaN,
"side": "BUY",
"srcAmount": "---",
"srcDecimals": 18,
Expand Down
86 changes: 4 additions & 82 deletions tests/__snapshots__/partialSdk.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,44 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Partial SDK: fetching methods: axiosFetcher Get_Adapters: Get_Adapters 1`] = `
[
"CurveV2",
"Lido",
"EtherFi",
"CurveV1",
"BalancerV1",
"BalancerV2",
"UniswapV2",
"DefiSwap",
"SushiSwap",
"ShibaSwap",
"Verse",
"UniswapV3",
"SushiSwapV3",
"PancakeSwapV2",
"PancakeswapV3",
"AaveV3",
"AaveV3Lido",
"Weth",
"PolygonMigrator",
"Synapse",
"Synthetix",
"CurveV1Factory",
"CurveV1StableNg",
"wstETH",
"Hashflow",
"MaverickV1",
"SwaapV2",
"AngleStakedStableUSD",
"AngleStakedStableEUR",
"SolidlyV3",
"Swell",
"Spark",
"sUSDS",
"AugustusRFQ",
]
`;

exports[`Partial SDK: fetching methods: axiosFetcher Get_Contracts: axiosFetcher 1`] = `
{
"AugustusRFQ": "0xe92b586627ccA7a83dC919cc7127196d70f55a06",
Expand Down Expand Up @@ -77,7 +38,7 @@ exports[`Partial SDK: fetching methods: axiosFetcher Get_SwapTxData: Get_SwapTxD
],
"blockNumber": "dynamic_number",
"contractAddress": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
"contractMethod": "swapOnUniswapV2Fork",
"contractMethod": "simpleSwap",
"destAmount": "dynamic_number",
"destDecimals": 18,
"destToken": "0x6b175474e89094c44da98b954eedeac495271d0f",
Expand All @@ -88,7 +49,7 @@ exports[`Partial SDK: fetching methods: axiosFetcher Get_SwapTxData: Get_SwapTxD
"maxImpactReached": false,
"network": 1,
"partner": "anon",
"partnerFee": 0,
"partnerFee": NaN,
"side": "SELL",
"srcAmount": "1000000000000000000",
"srcDecimals": 18,
Expand All @@ -110,45 +71,6 @@ exports[`Partial SDK: fetching methods: axiosFetcher Get_SwapTxData: Get_SwapTxD
}
`;

exports[`Partial SDK: fetching methods: fetchFetcher Get_Adapters: Get_Adapters 1`] = `
[
"CurveV2",
"Lido",
"EtherFi",
"CurveV1",
"BalancerV1",
"BalancerV2",
"UniswapV2",
"DefiSwap",
"SushiSwap",
"ShibaSwap",
"Verse",
"UniswapV3",
"SushiSwapV3",
"PancakeSwapV2",
"PancakeswapV3",
"AaveV3",
"AaveV3Lido",
"Weth",
"PolygonMigrator",
"Synapse",
"Synthetix",
"CurveV1Factory",
"CurveV1StableNg",
"wstETH",
"Hashflow",
"MaverickV1",
"SwaapV2",
"AngleStakedStableUSD",
"AngleStakedStableEUR",
"SolidlyV3",
"Swell",
"Spark",
"sUSDS",
"AugustusRFQ",
]
`;

exports[`Partial SDK: fetching methods: fetchFetcher Get_Contracts: fetchFetcher 1`] = `
{
"AugustusRFQ": "0xe92b586627ccA7a83dC919cc7127196d70f55a06",
Expand Down Expand Up @@ -187,7 +109,7 @@ exports[`Partial SDK: fetching methods: fetchFetcher Get_SwapTxData: Get_SwapTxD
],
"blockNumber": "dynamic_number",
"contractAddress": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57",
"contractMethod": "swapOnUniswapV2Fork",
"contractMethod": "simpleSwap",
"destAmount": "dynamic_number",
"destDecimals": 18,
"destToken": "0x6b175474e89094c44da98b954eedeac495271d0f",
Expand All @@ -198,7 +120,7 @@ exports[`Partial SDK: fetching methods: fetchFetcher Get_SwapTxData: Get_SwapTxD
"maxImpactReached": false,
"network": 1,
"partner": "anon",
"partnerFee": 0,
"partnerFee": NaN,
"side": "SELL",
"srcAmount": "1000000000000000000",
"srcDecimals": 18,
Expand Down
4 changes: 2 additions & 2 deletions tests/__snapshots__/quote.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ exports[`Quote:methods Get Fallback Market Quote for all 2`] = `
"maxImpactReached": false,
"network": 1,
"partner": "anon",
"partnerFee": 0,
"partnerFee": NaN,
"side": "SELL",
"srcAmount": "100000",
"srcAmount": "10000",
"srcDecimals": 6,
"srcToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"srcUSD": "dynamic_number",
Expand Down
Loading
Loading