From dc65db17d0b585a12af2d2b70765b24cb80b210e Mon Sep 17 00:00:00 2001 From: Evan Pipta <3pipta@gmail.com> Date: Tue, 7 Nov 2023 13:02:54 +0100 Subject: [PATCH 1/3] sdk: cancel existing orders tx feature --- sdk/src/driftClient.ts | 60 +++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index 597f2635b..e7b610ff8 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -2448,6 +2448,7 @@ export class DriftClient { * @param makerInfo * @param txParams * @param bracketOrdersParams + * @param cancelExistingOrders - Builds and returns an extra transaciton to cancel the existing orders in the same market. Intended use is to auto-cancel TP/SL orders when closing a position * @returns */ public async sendMarketOrderAndGetSignedFillTx( @@ -2457,8 +2458,13 @@ export class DriftClient { makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams = new Array(), - referrerInfo?: ReferrerInfo - ): Promise<{ txSig: TransactionSignature; signedFillTx: Transaction }> { + referrerInfo?: ReferrerInfo, + cancelExistingOrders?: boolean + ): Promise<{ + txSig: TransactionSignature; + signedFillTx: Transaction; + signedCancelExistingOrdersTx: Transaction; + }> { const marketIndex = orderParams.marketIndex; const orderId = userAccount.nextOrderId; const bracketOrderIxs = []; @@ -2483,6 +2489,22 @@ export class DriftClient { referrerInfo ); + let cancelOrdersIx: TransactionInstruction; + let cancelExistingOrdersTx: Transaction; + if (cancelExistingOrders) { + console.log('cancel existing orders'); + cancelOrdersIx = await this.getCancelOrdersIx( + orderParams.marketType, + orderParams.marketIndex, + null + ); + cancelExistingOrdersTx = (await this.buildTransaction( + [cancelOrdersIx], + txParams, + this.txVersion + )) as Transaction; + } + // use versioned transactions if there is a lookup table account and wallet is compatible if (this.txVersion === 0) { const versionedMarketOrderTx = await this.buildTransaction( @@ -2495,21 +2517,31 @@ export class DriftClient { txParams, 0 ); - const [signedVersionedMarketOrderTx, signedVersionedFillTx] = - await this.provider.wallet.signAllTransactions([ - //@ts-ignore + + const [ + signedVersionedMarketOrderTx, + signedVersionedFillTx, + signedCancelExistingOrdersTx, + ] = await this.provider.wallet.signAllTransactions( + [ versionedMarketOrderTx, - //@ts-ignore versionedFillTx, - ]); + cancelExistingOrdersTx, + ].filter((tx) => tx !== undefined) + ); const { txSig, slot } = await this.txSender.sendRawTransaction( signedVersionedMarketOrderTx.serialize(), this.opts ); this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot); - // @ts-ignore - return { txSig, signedFillTx: signedVersionedFillTx }; + return { + txSig, + // @ts-ignore + signedFillTx: signedVersionedFillTx, + // @ts-ignore + signedCancelExistingOrdersTx, + }; } else { const marketOrderTx = wrapInTx( placePerpOrderIx, @@ -2537,8 +2569,12 @@ export class DriftClient { marketOrderTx.feePayer = userAccount.authority; fillTx.feePayer = userAccount.authority; - const [signedMarketOrderTx, signedFillTx] = - await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]); + const [signedMarketOrderTx, signedFillTx, signedCancelExistingOrdersTx] = + await this.provider.wallet.signAllTransactions( + [marketOrderTx, fillTx, cancelExistingOrdersTx].filter( + (tx) => tx !== undefined + ) + ); const { txSig, slot } = await this.sendTransaction( signedMarketOrderTx, [], @@ -2547,7 +2583,7 @@ export class DriftClient { ); this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot); - return { txSig, signedFillTx }; + return { txSig, signedFillTx, signedCancelExistingOrdersTx }; } } From f978e641c61b7c85b12b584479052b54b1c74763 Mon Sep 17 00:00:00 2001 From: Evan Pipta <3pipta@gmail.com> Date: Wed, 8 Nov 2023 12:02:59 +0100 Subject: [PATCH 2/3] sdk: divide by zero bugfix --- sdk/src/math/trade.ts | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/sdk/src/math/trade.ts b/sdk/src/math/trade.ts index bd15eb407..3ce7d4dc9 100644 --- a/sdk/src/math/trade.ts +++ b/sdk/src/math/trade.ts @@ -649,15 +649,15 @@ export function calculateEstimatedPerpEntryPrice( } } - const entryPrice = cumulativeQuoteFilled - .mul(BASE_PRECISION) - .div(cumulativeBaseFilled); + const entryPrice = + cumulativeBaseFilled && cumulativeBaseFilled.gt(ZERO) + ? cumulativeQuoteFilled.mul(BASE_PRECISION).div(cumulativeBaseFilled) + : ZERO; - const priceImpact = entryPrice - .sub(bestPrice) - .mul(PRICE_PRECISION) - .div(bestPrice) - .abs(); + const priceImpact = + bestPrice && bestPrice.gt(ZERO) + ? entryPrice.sub(bestPrice).mul(PRICE_PRECISION).div(bestPrice).abs() + : ZERO; return { entryPrice, @@ -858,15 +858,15 @@ export function calculateEstimatedSpotEntryPrice( } } - const entryPrice = cumulativeQuoteFilled - .mul(basePrecision) - .div(cumulativeBaseFilled); + const entryPrice = + cumulativeBaseFilled && cumulativeBaseFilled.gt(ZERO) + ? cumulativeQuoteFilled.mul(basePrecision).div(cumulativeBaseFilled) + : ZERO; - const priceImpact = entryPrice - .sub(bestPrice) - .mul(PRICE_PRECISION) - .div(bestPrice) - .abs(); + const priceImpact = + bestPrice && bestPrice.gt(ZERO) + ? entryPrice.sub(bestPrice).mul(PRICE_PRECISION).div(bestPrice).abs() + : ZERO; return { entryPrice, @@ -900,8 +900,8 @@ export function calculateEstimatedEntryPriceWithL2( const levels = [...(takerIsLong ? l2.asks : l2.bids)]; let nextLevel = levels.shift(); - let bestPrice; - let worstPrice; + let bestPrice: BN; + let worstPrice: BN; if (nextLevel) { bestPrice = nextLevel.price; worstPrice = nextLevel.price; @@ -945,15 +945,15 @@ export function calculateEstimatedEntryPriceWithL2( } } - const entryPrice = cumulativeQuoteFilled - .mul(basePrecision) - .div(cumulativeBaseFilled); + const entryPrice = + cumulativeBaseFilled && cumulativeBaseFilled.gt(ZERO) + ? cumulativeQuoteFilled.mul(basePrecision).div(cumulativeBaseFilled) + : ZERO; - const priceImpact = entryPrice - .sub(bestPrice) - .mul(PRICE_PRECISION) - .div(bestPrice) - .abs(); + const priceImpact = + bestPrice && bestPrice.gt(ZERO) + ? entryPrice.sub(bestPrice).mul(PRICE_PRECISION).div(bestPrice).abs() + : ZERO; return { entryPrice, From 50af37667f38d82161141d640c6780df529db0cb Mon Sep 17 00:00:00 2001 From: Evan Pipta <3pipta@gmail.com> Date: Wed, 8 Nov 2023 18:18:28 +0100 Subject: [PATCH 3/3] sdk: fix cancel existing orders feedback --- sdk/src/driftClient.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index e7b610ff8..9d5cdb91f 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -2463,7 +2463,7 @@ export class DriftClient { ): Promise<{ txSig: TransactionSignature; signedFillTx: Transaction; - signedCancelExistingOrdersTx: Transaction; + signedCancelExistingOrdersTx?: Transaction; }> { const marketIndex = orderParams.marketIndex; const orderId = userAccount.nextOrderId; @@ -2492,17 +2492,18 @@ export class DriftClient { let cancelOrdersIx: TransactionInstruction; let cancelExistingOrdersTx: Transaction; if (cancelExistingOrders) { - console.log('cancel existing orders'); cancelOrdersIx = await this.getCancelOrdersIx( orderParams.marketType, orderParams.marketIndex, null ); - cancelExistingOrdersTx = (await this.buildTransaction( + + //@ts-ignore + cancelExistingOrdersTx = await this.buildTransaction( [cancelOrdersIx], txParams, this.txVersion - )) as Transaction; + ); } // use versioned transactions if there is a lookup table account and wallet is compatible