Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
108 changes: 97 additions & 11 deletions src/methods/delta/buildDeltaOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import {
} from './helpers/buildDeltaOrderData';
import { SwapSideToOrderKind } from './helpers/types';
import { SwapSide } from '../../constants';
import type { MarkOptional } from 'ts-essentials';
import { assert, type MarkOptional } from 'ts-essentials';
import { ZERO_ADDRESS } from '../common/orders/buildOrderData';
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 !== undefined
? 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({
amount: options.deltaPrice.destAmount,
slippageBps: options.slippage,
increase: false,
});
} else {
// BUY with slippage: srcAmount auto-computed
destAmount = options.destAmount;
srcAmount = applySlippage({
amount: options.deltaPrice.srcAmount,
slippageBps: options.slippage,
increase: 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,28 @@ export const constructBuildDeltaOrder = (
buildDeltaOrder,
};
};

type ApplySlippageInput = {
amount: string;
slippageBps: number;
increase: boolean;
};

function applySlippage({
amount,
slippageBps,
increase,
}: ApplySlippageInput): string {
assert(
Number.isInteger(slippageBps) && slippageBps >= 0 && slippageBps <= 10_000,
'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);
}
Loading
Loading