diff --git a/sdk/src/config.ts b/sdk/src/config.ts index 0ff967b7a..3e6420031 100644 --- a/sdk/src/config.ts +++ b/sdk/src/config.ts @@ -136,15 +136,15 @@ export function getMarketsAndOraclesForSubscription( oracleInfos: OracleInfo[]; } { const perpMarketsToUse = - perpMarkets?.length > 0 ? perpMarkets : PerpMarkets[env]; + (perpMarkets?.length ?? 0) > 0 ? perpMarkets : PerpMarkets[env]; const spotMarketsToUse = - spotMarkets?.length > 0 ? spotMarkets : SpotMarkets[env]; + (spotMarkets?.length ?? 0) > 0 ? spotMarkets : SpotMarkets[env]; const perpMarketIndexes = []; const spotMarketIndexes = []; const oracleInfos = new Map(); - for (const market of perpMarketsToUse) { + for (const market of perpMarketsToUse ?? []) { perpMarketIndexes.push(market.marketIndex); oracleInfos.set(getOracleId(market.oracle, market.oracleSource), { publicKey: market.oracle, @@ -152,7 +152,7 @@ export function getMarketsAndOraclesForSubscription( }); } - for (const spotMarket of spotMarketsToUse) { + for (const spotMarket of spotMarketsToUse ?? []) { spotMarketIndexes.push(spotMarket.marketIndex); oracleInfos.set(getOracleId(spotMarket.oracle, spotMarket.oracleSource), { publicKey: spotMarket.oracle, diff --git a/sdk/src/constants/txConstants.ts b/sdk/src/constants/txConstants.ts index df3e00180..c16c23eae 100644 --- a/sdk/src/constants/txConstants.ts +++ b/sdk/src/constants/txConstants.ts @@ -4,3 +4,5 @@ export const NOT_CONFIRMED_ERROR_CODE = -1001; export const FUEL_RESET_LOG_ACCOUNT = new PublicKey( 'FuE1gqp2fzw2sDNLrbZqKsqpphJcoSW6HPaSJjGd4RZ4' ); + +export const DEFAULT_COMMITMENT_LEVEL = 'confirmed'; diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index 8b0ef4cad..dee971338 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -221,6 +221,7 @@ import { } from './math/builder'; import { TitanClient, SwapMode as TitanSwapMode } from './titan/titanClient'; import { UnifiedSwapClient } from './swap/UnifiedSwapClient'; +import { DEFAULT_COMMITMENT_LEVEL } from './constants'; /** * Union type for swap clients (Titan and Jupiter) - Legacy type @@ -428,19 +429,17 @@ export class DriftClient { }); } - this.marketLookupTable = config.marketLookupTable; - if (!this.marketLookupTable) { - this.marketLookupTable = new PublicKey( - configs[this.env].MARKET_LOOKUP_TABLE - ); - } + this.marketLookupTable = config.marketLookupTable + ? config.marketLookupTable + : (this.marketLookupTable = new PublicKey( + configs[this.env].MARKET_LOOKUP_TABLE + )); - this.marketLookupTables = config.marketLookupTables; - if (!this.marketLookupTables) { - this.marketLookupTables = configs[this.env].MARKET_LOOKUP_TABLES.map( - (tableAddr) => new PublicKey(tableAddr) - ); - } + this.marketLookupTables = config.marketLookupTables + ? config.marketLookupTables + : configs[this.env].MARKET_LOOKUP_TABLES.map( + (tableAddr) => new PublicKey(tableAddr) + ); const delistedMarketSetting = config.delistedMarketSetting || DelistedMarketSetting.Unsubscribe; @@ -4517,7 +4516,10 @@ export class DriftClient { public getQuoteValuePerLpShare(marketIndex: number): BN { const perpMarketAccount = this.getPerpMarketAccount(marketIndex); - + if(!perpMarketAccount) { + throw new Error(`Perp market account not found for market index ${marketIndex}`); + } + const openBids = BN.max( perpMarketAccount.amm.baseAssetReserve.sub( perpMarketAccount.amm.minBaseAssetReserve @@ -4789,7 +4791,15 @@ export class DriftClient { const remainingAccounts = this.getRemainingAccounts({ userAccounts: depositToTradeArgs?.isMakingNewAccount ? [] - : [this.getUserAccount(subAccountId)], + : (() => { + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } + return [userAccount]; + })(), useMarketLastSlotCache: false, readablePerpMarketIndex: orderParams.marketIndex, readableSpotMarketIndexes: isDepositToTradeTx @@ -4797,7 +4807,7 @@ export class DriftClient { : undefined, }); - if (isUpdateHighLeverageMode(orderParams.bitFlags)) { + if (isUpdateHighLeverageMode(orderParams.bitFlags ?? 0)) { remainingAccounts.push({ pubkey: getHighLeverageModeConfigPublicKey(this.program.programId), isWritable: true, @@ -4838,6 +4848,9 @@ export class DriftClient { const oracleAccountInfos = []; for (const marketIndex of marketIndexes) { const market = this.getPerpMarketAccount(marketIndex); + if (!market) { + continue; + } marketAccountInfos.push({ pubkey: market.pubkey, isWritable: true, @@ -4963,9 +4976,14 @@ export class DriftClient { subAccountId?: number ): Promise { const user = await this.getUserAccountPublicKey(subAccountId); - + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], useMarketLastSlotCache: true, }); @@ -5002,10 +5020,22 @@ export class DriftClient { const user = await this.getUserAccountPublicKey(subAccountId); const order = this.getOrderByUserId(userOrderId); - const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle; + const oracle = this.getPerpMarketAccount(order?.marketIndex ?? 0)?.amm + .oracle; + if (!oracle) { + throw new Error( + `Oracle not found for market index ${order?.marketIndex ?? 0}` + ); + } + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], useMarketLastSlotCache: true, }); @@ -5075,6 +5105,11 @@ export class DriftClient { (await this.getUserAccountPublicKey(subAccountId)); const userAccount = user?.getUserAccount() ?? this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ userAccounts: [userAccount], @@ -5103,9 +5138,9 @@ export class DriftClient { const { txSig } = await this.sendTransaction( await this.buildTransaction( await this.getCancelOrdersIx( - marketType, - marketIndex, - direction, + marketType ?? null, + marketIndex ?? null, + direction ?? null, subAccountId ), txParams @@ -5135,8 +5170,15 @@ export class DriftClient { } } + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } + const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], readablePerpMarketIndex, readableSpotMarketIndexes, useMarketLastSlotCache: true, @@ -5169,9 +5211,9 @@ export class DriftClient { ): Promise { const ixs = [ await this.getCancelOrdersIx( - cancelOrderParams.marketType, - cancelOrderParams.marketIndex, - cancelOrderParams.direction, + cancelOrderParams.marketType ?? null, + cancelOrderParams.marketIndex ?? null, + cancelOrderParams.direction ?? null, subAccountId ), await this.getPlaceOrdersIx(placeOrderParams, subAccountId), @@ -5248,15 +5290,22 @@ export class DriftClient { } } + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } + const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], readablePerpMarketIndex, readableSpotMarketIndexes, useMarketLastSlotCache: true, }); for (const param of params) { - if (isUpdateHighLeverageMode(param.bitFlags)) { + if (isUpdateHighLeverageMode(param.bitFlags ?? 0)) { remainingAccounts.push({ pubkey: getHighLeverageModeConfigPublicKey(this.program.programId), isWritable: true, @@ -5298,16 +5347,22 @@ export class DriftClient { readableSpotMarketIndexes.push(param.marketIndex); } } + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], readablePerpMarketIndex, readableSpotMarketIndexes, useMarketLastSlotCache: true, }); for (const param of params) { - if (isUpdateHighLeverageMode(param.bitFlags)) { + if (isUpdateHighLeverageMode(param.bitFlags ?? 0)) { remainingAccounts.push({ pubkey: getHighLeverageModeConfigPublicKey(this.program.programId), isWritable: true, @@ -5362,7 +5417,7 @@ export class DriftClient { await this.getFillPerpOrderIx( userAccountPublicKey, user, - order, + order as Pick, makerInfo, referrerInfo, fillerSubAccountId, @@ -5421,7 +5476,10 @@ export class DriftClient { ? order.marketIndex : userAccount.orders.find( (order) => order.orderId === userAccount.nextOrderId - 1 - ).marketIndex; + )?.marketIndex; + if (!marketIndex) { + throw new Error(`Market index not found`); + } makerInfo = Array.isArray(makerInfo) ? makerInfo @@ -5569,9 +5627,15 @@ export class DriftClient { const userAccountPublicKey = await this.getUserAccountPublicKey( subAccountId ); + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], useMarketLastSlotCache: true, readableSpotMarketIndexes: [ orderParams.marketIndex, @@ -5643,8 +5707,11 @@ export class DriftClient { const marketIndex = order ? order.marketIndex : userAccount.orders.find( - (order) => order.orderId === userAccount.nextOrderId - 1 - ).marketIndex; + (o) => o.orderId === userAccount.nextOrderId - 1 + )?.marketIndex; + if (!marketIndex) { + throw new Error(`Market index not found`); + } makerInfo = Array.isArray(makerInfo) ? makerInfo @@ -5674,7 +5741,7 @@ export class DriftClient { }); } - const orderId = order.orderId; + const orderId = order?.orderId; this.addSpotFulfillmentAccounts( marketIndex, @@ -5708,6 +5775,10 @@ export class DriftClient { | PhoenixV1FulfillmentConfigAccount | OpenbookV2FulfillmentConfigAccount ): void { + const market = this.getSpotMarketAccount(marketIndex); + if (!market) { + throw new Error(`Market not found`); + } if (fulfillmentConfig) { if ('serumProgramId' in fulfillmentConfig) { this.addSerumRemainingAccounts( @@ -5732,7 +5803,7 @@ export class DriftClient { } } else { remainingAccounts.push({ - pubkey: this.getSpotMarketAccount(marketIndex).vault, + pubkey: market.vault, isWritable: false, isSigner: false, }); @@ -5749,6 +5820,10 @@ export class DriftClient { remainingAccounts: AccountMeta[], fulfillmentConfig: SerumV3FulfillmentConfigAccount ): void { + const market = this.getSpotMarketAccount(marketIndex); + if (!market) { + throw new Error(`Market not found`); + } remainingAccounts.push({ pubkey: fulfillmentConfig.pubkey, isWritable: false, @@ -5819,7 +5894,7 @@ export class DriftClient { isSigner: false, }); remainingAccounts.push({ - pubkey: this.getSpotMarketAccount(marketIndex).vault, + pubkey: market.vault, isWritable: true, isSigner: false, }); @@ -5840,6 +5915,10 @@ export class DriftClient { remainingAccounts: AccountMeta[], fulfillmentConfig: PhoenixV1FulfillmentConfigAccount ): void { + const market = this.getSpotMarketAccount(marketIndex); + if (!market) { + throw new Error(`Market not found`); + } remainingAccounts.push({ pubkey: fulfillmentConfig.pubkey, isWritable: false, @@ -5876,7 +5955,7 @@ export class DriftClient { isSigner: false, }); remainingAccounts.push({ - pubkey: this.getSpotMarketAccount(marketIndex).vault, + pubkey: market.vault, isWritable: true, isSigner: false, }); @@ -5897,6 +5976,10 @@ export class DriftClient { remainingAccounts: AccountMeta[], fulfillmentConfig: OpenbookV2FulfillmentConfigAccount ): void { + const market = this.getSpotMarketAccount(marketIndex); + if (!market) { + throw new Error(`Market not found`); + } remainingAccounts.push({ pubkey: fulfillmentConfig.pubkey, isWritable: false, @@ -5948,7 +6031,7 @@ export class DriftClient { isSigner: false, }); remainingAccounts.push({ - pubkey: this.getSpotMarketAccount(marketIndex).vault, + pubkey: market.vault, isWritable: true, isSigner: false, }); @@ -5968,7 +6051,7 @@ export class DriftClient { isSigner: false, }); remainingAccounts.push({ - pubkey: this.getSpotMarketAccount(marketIndex).pubkey, + pubkey: market.pubkey, isWritable: true, isSigner: false, }); @@ -6149,6 +6232,9 @@ export class DriftClient { }> { const outMarket = this.getSpotMarketAccount(outMarketIndex); const inMarket = this.getSpotMarketAccount(inMarketIndex); + if (!outMarket || !inMarket) { + throw new Error(`Out or in market not found`); + } const isExactOut = swapMode === 'ExactOut'; const exactOutBufferedAmountIn = amount.muln(1001).divn(1000); // Add 10bp buffer @@ -6271,6 +6357,9 @@ export class DriftClient { }> { const outMarket = this.getSpotMarketAccount(outMarketIndex); const inMarket = this.getSpotMarketAccount(inMarketIndex); + if (!outMarket || !inMarket) { + throw new Error(`Out or in market not found`); + } if (!quote) { const fetchedQuote = await jupiterClient.getQuote({ @@ -6433,6 +6522,9 @@ export class DriftClient { const outSpotMarket = this.getSpotMarketAccount(outMarketIndex); const inSpotMarket = this.getSpotMarketAccount(inMarketIndex); + if (!outSpotMarket || !inSpotMarket) { + throw new Error(`Out or in spot market not found`); + } const outTokenProgram = this.getTokenProgramForSpotMarket(outSpotMarket); const inTokenProgram = this.getTokenProgramForSpotMarket(inSpotMarket); @@ -6555,6 +6647,9 @@ export class DriftClient { // Get market accounts to determine mints const outMarket = this.getSpotMarketAccount(outMarketIndex); const inMarket = this.getSpotMarketAccount(inMarketIndex); + if (!outMarket || !inMarket) { + throw new Error(`Out or in market not found`); + } const isExactOut = swapMode === 'ExactOut'; @@ -6674,7 +6769,10 @@ export class DriftClient { amount: BN; userAccountPublicKey?: PublicKey; }): Promise { - const wSOLMint = this.getSpotMarketAccount(1).mint; + const wSOLMint = this.getSpotMarketAccount(1)?.mint; + if (!wSOLMint) { + throw new Error(`W SOL mint not found`); + } const mSOLAccount = await this.getAssociatedTokenAccount(2); const wSOLAccount = await this.getAssociatedTokenAccount(1, false); @@ -7070,12 +7168,15 @@ export class DriftClient { placeAndTakeTx: Transaction | VersionedTransaction; cancelExistingOrdersTx: Transaction | VersionedTransaction; settlePnlTx: Transaction | VersionedTransaction; - }> { + } | null> { const placeAndTakeIxs: TransactionInstruction[] = []; type TxKeys = 'placeAndTakeTx' | 'cancelExistingOrdersTx' | 'settlePnlTx'; - const txsToSign: Record = { + const txsToSign: Record< + TxKeys, + Transaction | VersionedTransaction | undefined + > = { placeAndTakeTx: undefined, cancelExistingOrdersTx: undefined, settlePnlTx: undefined, @@ -7133,8 +7234,8 @@ export class DriftClient { await TransactionParamProcessor.getTxSimComputeUnits( placeAndTakeTxToSim, this.connection, - txParams.computeUnitsBufferMultiplier ?? 1.2, - txParams.lowerBoundCu + txParams?.computeUnitsBufferMultiplier ?? 1.2, + txParams?.lowerBoundCu ); if (shouldExitIfSimulationFails && !simulationResult.success) { @@ -7170,7 +7271,11 @@ export class DriftClient { }; const prepCancelOrderTx = async () => { - if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) { + if ( + cancelExistingOrders && + orderParams.marketType && + isVariant(orderParams.marketType, 'perp') + ) { const cancelOrdersIx = await this.getCancelOrdersIx( orderParams.marketType, orderParams.marketIndex, @@ -7198,9 +7303,16 @@ export class DriftClient { subAccountId ); + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } + const settlePnlIx = await this.settlePNLIx( userAccountPublicKey, - this.getUserAccount(subAccountId), + userAccount, orderParams.marketIndex ); @@ -7227,7 +7339,11 @@ export class DriftClient { return null; } - return txsToSign; + return txsToSign as { + placeAndTakeTx: Transaction | VersionedTransaction; + cancelExistingOrdersTx: Transaction | VersionedTransaction; + settlePnlTx: Transaction | VersionedTransaction; + }; } public async placeAndTakePerpWithAdditionalOrders( @@ -7244,7 +7360,7 @@ export class DriftClient { txSig: TransactionSignature; signedCancelExistingOrdersTx?: Transaction; signedSettlePnlTx?: Transaction; - }> { + } | null> { const txsToSign = await this.preparePlaceAndTakePerpOrderWithAdditionalOrders( orderParams, @@ -7308,7 +7424,13 @@ export class DriftClient { ? [makerInfo] : []; - const userAccounts = [this.getUserAccount(subAccountId)]; + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } + const userAccounts = [userAccount]; for (const maker of makerInfo) { userAccounts.push(maker.makerUserAccount); } @@ -7350,7 +7472,7 @@ export class DriftClient { } } - if (isUpdateHighLeverageMode(orderParams.bitFlags)) { + if (isUpdateHighLeverageMode(orderParams.bitFlags ?? 0)) { remainingAccounts.push({ pubkey: getHighLeverageModeConfigPublicKey(this.program.programId), isWritable: true, @@ -7416,12 +7538,15 @@ export class DriftClient { orderParams = getOrderParams(orderParams, { marketType: MarketType.PERP }); const userStatsPublicKey = this.getUserStatsAccountPublicKey(); const user = await this.getUserAccountPublicKey(subAccountId); + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [ - this.getUserAccount(subAccountId), - takerInfo.takerUserAccount, - ], + userAccounts: [userAccount, takerInfo.takerUserAccount], useMarketLastSlotCache: true, writablePerpMarketIndexes: [orderParams.marketIndex], }); @@ -7590,8 +7715,11 @@ export class DriftClient { public signMessage( message: Uint8Array, - keypair: Keypair = this.wallet.payer + keypair: Keypair | undefined = this.wallet.payer ): Buffer { + if (!keypair) { + throw new Error(`Keypair not found for signMessage`); + } return Buffer.from(nacl.sign.detached(message, keypair.secretKey)); } @@ -7788,12 +7916,15 @@ export class DriftClient { orderParams = getOrderParams(orderParams, { marketType: MarketType.PERP }); const userStatsPublicKey = this.getUserStatsAccountPublicKey(); const user = await this.getUserAccountPublicKey(subAccountId); + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [ - this.getUserAccount(subAccountId), - takerInfo.takerUserAccount, - ], + userAccounts: [userAccount, takerInfo.takerUserAccount], useMarketLastSlotCache: false, writablePerpMarketIndexes: [orderParams.marketIndex], }); @@ -7927,8 +8058,14 @@ export class DriftClient { orderParams = getOrderParams(orderParams, { marketType: MarketType.SPOT }); const userStatsPublicKey = this.getUserStatsAccountPublicKey(); const user = await this.getUserAccountPublicKey(subAccountId); + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } - const userAccounts = [this.getUserAccount(subAccountId)]; + const userAccounts = [userAccount]; if (makerInfo !== undefined) { userAccounts.push(makerInfo.makerUserAccount); } @@ -7942,7 +8079,7 @@ export class DriftClient { }); let makerOrderId = null; - if (makerInfo) { + if (makerInfo && makerInfo.order) { makerOrderId = makerInfo.order.orderId; remainingAccounts.push({ pubkey: makerInfo.maker, @@ -8028,12 +8165,14 @@ export class DriftClient { orderParams = getOrderParams(orderParams, { marketType: MarketType.SPOT }); const userStatsPublicKey = this.getUserStatsAccountPublicKey(); const user = await this.getUserAccountPublicKey(subAccountId); - + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [ - this.getUserAccount(subAccountId), - takerInfo.takerUserAccount, - ], + userAccounts: [userAccount, takerInfo.takerUserAccount], useMarketLastSlotCache: true, writableSpotMarketIndexes: [ orderParams.marketIndex, @@ -8258,6 +8397,9 @@ export class DriftClient { (await this.getUserAccountPublicKey(subAccountId)); const userAccount = overrides?.user?.getUserAccount() ?? this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error(`User account not found`); + } const remainingAccounts = this.getRemainingAccounts({ userAccounts: [userAccount], @@ -8384,9 +8526,15 @@ export class DriftClient { subAccountId?: number ): Promise { const user = await this.getUserAccountPublicKey(subAccountId); + const userAccount = this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subaccount id ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(subAccountId)], + userAccounts: [userAccount], useMarketLastSlotCache: true, }); @@ -8443,7 +8591,13 @@ export class DriftClient { if (filterInvalidMarkets) { for (const marketIndex of marketIndexes) { const perpMarketAccount = this.getPerpMarketAccount(marketIndex); + if (!perpMarketAccount) { + continue; + } const oraclePriceData = this.getOracleDataForPerpMarket(marketIndex); + if (!oraclePriceData) { + continue; + } const stateAccountAndSlot = this.accountSubscriber.getStateAccountAndSlot(); const oracleGuardRails = stateAccountAndSlot.data.oracleGuardRails; @@ -8923,9 +9077,15 @@ export class DriftClient { liquidatorSubAccountId ); const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey(); + const liquidatorUser = this.getUserAccount(liquidatorSubAccountId); + if (!liquidatorUser) { + throw new Error( + `Liquidator user account not found for subaccount id ${liquidatorSubAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(liquidatorSubAccountId), userAccount], + userAccounts: [liquidatorUser, userAccount], useMarketLastSlotCache: true, writablePerpMarketIndexes: [marketIndex], }); @@ -9075,8 +9235,14 @@ export class DriftClient { ); const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey(); + const liquidatorUser = this.getUserAccount(liquidatorSubAccountId); + if (!liquidatorUser) { + throw new Error( + `Liquidator user account not found for subaccount id ${liquidatorSubAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(liquidatorSubAccountId), userAccount], + userAccounts: [liquidatorUser, userAccount], useMarketLastSlotCache: true, writableSpotMarketIndexes: [liabilityMarketIndex, assetMarketIndex], }); @@ -9137,7 +9303,17 @@ export class DriftClient { lookupTables: AddressLookupTableAccount[]; }> { const liabilityMarket = this.getSpotMarketAccount(liabilityMarketIndex); + if (!liabilityMarket) { + throw new Error( + `Liability spot market account not found for index ${liabilityMarketIndex}` + ); + } const assetMarket = this.getSpotMarketAccount(assetMarketIndex); + if (!assetMarket) { + throw new Error( + `Asset spot market account not found for index ${assetMarketIndex}` + ); + } if (!quote) { const fetchedQuote = await jupiterClient.getQuote({ @@ -9176,7 +9352,7 @@ export class DriftClient { outputMint: liabilityMarket.mint, }); - const preInstructions = []; + const preInstructions: TransactionInstruction[] = []; if (!liabilityTokenAccount) { const tokenProgram = this.getTokenProgramForSpotMarket(liabilityMarket); liabilityTokenAccount = await this.getAssociatedTokenAccount( @@ -9286,7 +9462,17 @@ export class DriftClient { }); const liabilitySpotMarket = this.getSpotMarketAccount(liabilityMarketIndex); + if (!liabilitySpotMarket) { + throw new Error( + `Liability spot market account not found for index ${liabilityMarketIndex}` + ); + } const assetSpotMarket = this.getSpotMarketAccount(assetMarketIndex); + if (!assetSpotMarket) { + throw new Error( + `Asset spot market account not found for index ${assetMarketIndex}` + ); + } const liabilityTokenProgram = this.getTokenProgramForSpotMarket(liabilitySpotMarket); @@ -9402,7 +9588,17 @@ export class DriftClient { }); const inSpotMarket = this.getSpotMarketAccount(inMarketIndex); + if (!inSpotMarket) { + throw new Error( + `In spot market account not found for index ${inMarketIndex}` + ); + } const outSpotMarket = this.getSpotMarketAccount(outMarketIndex); + if (!outSpotMarket) { + throw new Error( + `Out spot market account not found for index ${outMarketIndex}` + ); + } if (this.isToken2022(inSpotMarket) || this.isToken2022(outSpotMarket)) { remainingAccounts.push({ @@ -9528,9 +9724,15 @@ export class DriftClient { liquidatorSubAccountId ); const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey(); + const liquidatorUser = this.getUserAccount(liquidatorSubAccountId); + if (!liquidatorUser) { + throw new Error( + `Liquidator user account not found for subaccount id ${liquidatorSubAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(liquidatorSubAccountId), userAccount], + userAccounts: [liquidatorUser, userAccount], writablePerpMarketIndexes: [perpMarketIndex], writableSpotMarketIndexes: [liabilityMarketIndex], }); @@ -9603,9 +9805,15 @@ export class DriftClient { liquidatorSubAccountId ); const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey(); + const liquidatorUser = this.getUserAccount(liquidatorSubAccountId); + if (!liquidatorUser) { + throw new Error( + `Liquidator user account not found for subaccount id ${liquidatorSubAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(liquidatorSubAccountId), userAccount], + userAccounts: [liquidatorUser, userAccount], writablePerpMarketIndexes: [perpMarketIndex], writableSpotMarketIndexes: [assetMarketIndex], }); @@ -9667,9 +9875,15 @@ export class DriftClient { liquidatorSubAccountId ); const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey(); + const liquidatorUser = this.getUserAccount(liquidatorSubAccountId); + if (!liquidatorUser) { + throw new Error( + `Liquidator user account not found for subaccount id ${liquidatorSubAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(liquidatorSubAccountId), userAccount], + userAccounts: [liquidatorUser, userAccount], writablePerpMarketIndexes: [marketIndex], writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX], }); @@ -9736,12 +9950,22 @@ export class DriftClient { ); const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey(); + const liquidatorUser = this.getUserAccount(liquidatorSubAccountId); + if (!liquidatorUser) { + throw new Error( + `Liquidator user account not found for subaccount id ${liquidatorSubAccountId}` + ); + } + const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount(liquidatorSubAccountId), userAccount], + userAccounts: [liquidatorUser, userAccount], writableSpotMarketIndexes: [marketIndex], }); const spotMarket = this.getSpotMarketAccount(marketIndex); + if (!spotMarket) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const tokenProgramId = this.getTokenProgramForSpotMarket(spotMarket); this.addTokenMintToRemainingAccounts(spotMarket, remainingAccounts); @@ -9821,6 +10045,11 @@ export class DriftClient { perpMarketIndex: number ): Promise { const perpMarket = this.getPerpMarketAccount(perpMarketIndex); + if (!perpMarket) { + throw new Error( + `Perp market account not found for index ${perpMarketIndex}` + ); + } if (!isVariant(perpMarket.amm.oracleSource, 'prelaunch')) { throw new Error(`Wrong oracle source ${perpMarket.amm.oracleSource}`); @@ -9856,8 +10085,13 @@ export class DriftClient { makers: [PublicKey, PublicKey][] ): Promise { const perpMarket = this.getPerpMarketAccount(perpMarketIndex); + if (!perpMarket) { + throw new Error( + `Perp market account not found for index ${perpMarketIndex}` + ); + } - const remainingAccounts = []; + const remainingAccounts: AccountMeta[] = []; for (const [maker, makerStats] of makers) { remainingAccounts.push({ pubkey: maker, @@ -9905,7 +10139,7 @@ export class DriftClient { userAccountPublicKey )) as UserAccount; - const writablePerpMarketIndexes = []; + const writablePerpMarketIndexes: number[] = []; for (const position of userAccount.perpPositions) { if (!positionIsAvailable(position)) { writablePerpMarketIndexes.push(position.marketIndex); @@ -9929,16 +10163,34 @@ export class DriftClient { public triggerEvent(eventName: keyof DriftClientAccountEvents, data?: any) { this.eventEmitter.emit(eventName, data); } - - public getOracleDataForPerpMarket(marketIndex: number): OraclePriceData { - return this.accountSubscriber.getOraclePriceDataAndSlotForPerpMarket( + + /** + * This function can potentially throw an error when the driftClient is still initializing, even if you have awaited subscription, handle accordingly. + * @param marketIndex + * @returns + */ + public getOracleDataForPerpMarket( + marketIndex: number + ): OraclePriceData { + const oracleDataAndSlot = this.accountSubscriber.getOraclePriceDataAndSlotForPerpMarket( marketIndex - ).data; + ) + if(!oracleDataAndSlot) { + throw new Error(`DriftClient.getOracleDataForPerpMarket: Oracle data not found for perp market ${marketIndex}. + You may not have configured the driftClient to subscribe to this market, or may be calling this function before the data is ready.`); + } + return oracleDataAndSlot.data; } - public getMMOracleDataForPerpMarket(marketIndex: number): MMOraclePriceData { + public getMMOracleDataForPerpMarket( + marketIndex: number + ): MMOraclePriceData { const perpMarket = this.getPerpMarketAccount(marketIndex); + if (!perpMarket) { + throw new Error(`Perp market account not found for index ${marketIndex}`); + } const oracleData = this.getOracleDataForPerpMarket(marketIndex); + const stateAccountAndSlot = this.accountSubscriber.getStateAccountAndSlot(); const isMMOracleActive = !perpMarket.amm.mmOracleSlot.eq(ZERO); const pctDiff = perpMarket.amm.mmOraclePrice @@ -9967,7 +10219,7 @@ export class DriftClient { isExchangeOracleMoreRecent = false; } else if ( !doSlotCheckForRecency && - oracleData.sequenceId < mmOracleSequenceId + (oracleData.sequenceId ?? ZERO) < mmOracleSequenceId ) { isExchangeOracleMoreRecent = false; } @@ -10004,10 +10256,16 @@ export class DriftClient { } } - public getOracleDataForSpotMarket(marketIndex: number): OraclePriceData { - return this.accountSubscriber.getOraclePriceDataAndSlotForSpotMarket( - marketIndex - ).data; + public getOracleDataForSpotMarket( + marketIndex: number + ): OraclePriceData { + try { + return this.accountSubscriber.getOraclePriceDataAndSlotForSpotMarket( + marketIndex + ).data; + } catch (error) { + throw new Error(`Failed to get oracle data for spot market ${marketIndex}: ${error}`); + } } public async initializeInsuranceFundStake( @@ -10034,9 +10292,14 @@ export class DriftClient { marketIndex ); + const spotMarket = this.getSpotMarketAccount(marketIndex); + if (!spotMarket) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } + const accounts = { insuranceFundStake: ifStakeAccountPublicKey, - spotMarket: this.getSpotMarketAccount(marketIndex).pubkey, + spotMarket: spotMarket.pubkey, userStats: getUserStatsAccountPublicKey( this.program.programId, this.wallet.publicKey // only allow payer to initialize own insurance fund stake account @@ -10062,13 +10325,16 @@ export class DriftClient { collateralAccountPublicKey: PublicKey ): Promise { const spotMarket = this.getSpotMarketAccount(marketIndex); + if (!spotMarket) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey( this.program.programId, this.wallet.publicKey, marketIndex ); - const remainingAccounts = []; + const remainingAccounts: AccountMeta[] = []; this.addTokenMintToRemainingAccounts(spotMarket, remainingAccounts); if (this.isTransferHook(spotMarket)) { await this.addExtraAccountMetasToRemainingAccounts( @@ -10182,9 +10448,12 @@ export class DriftClient { */ fromSubaccount?: boolean; }): Promise { - const addIfStakeIxs = []; + const addIfStakeIxs: TransactionInstruction[] = []; const spotMarketAccount = this.getSpotMarketAccount(marketIndex); + if (!spotMarketAccount) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT); const createWSOLTokenAccount = isSolMarket && collateralAccountPublicKey.equals(this.wallet.publicKey); @@ -10278,6 +10547,9 @@ export class DriftClient { txParams?: TxParams ): Promise { const spotMarketAccount = this.getSpotMarketAccount(marketIndex); + if (!spotMarketAccount) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey( this.program.programId, this.wallet.publicKey, @@ -10313,6 +10585,9 @@ export class DriftClient { txParams?: TxParams ): Promise { const spotMarketAccount = this.getSpotMarketAccount(marketIndex); + if (!spotMarketAccount) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey( this.program.programId, this.wallet.publicKey, @@ -10348,8 +10623,11 @@ export class DriftClient { collateralAccountPublicKey: PublicKey, txParams?: TxParams ): Promise { - const removeIfStakeIxs = []; + const removeIfStakeIxs: TransactionInstruction[] = []; const spotMarketAccount = this.getSpotMarketAccount(marketIndex); + if (!spotMarketAccount) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey( this.program.programId, this.wallet.publicKey, @@ -10389,7 +10667,7 @@ export class DriftClient { } } - const remainingAccounts = []; + const remainingAccounts: AccountMeta[] = []; this.addTokenMintToRemainingAccounts(spotMarketAccount, remainingAccounts); if (this.isTransferHook(spotMarketAccount)) { await this.addExtraAccountMetasToRemainingAccounts( @@ -10459,6 +10737,9 @@ export class DriftClient { ): Promise { const marketIndex = QUOTE_SPOT_MARKET_INDEX; const spotMarket = this.getSpotMarketAccount(marketIndex); + if (!spotMarket) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey( this.program.programId, authority, @@ -10498,6 +10779,9 @@ export class DriftClient { ): Promise { const marketIndex = GOV_SPOT_MARKET_INDEX; const spotMarket = this.getSpotMarketAccount(marketIndex); + if (!spotMarket) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey( this.program.programId, authority, @@ -10538,9 +10822,14 @@ export class DriftClient { spotMarketIndex: number ): Promise { const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex); + if (!spotMarketAccount) { + throw new Error( + `Spot market account not found for index ${spotMarketIndex}` + ); + } const tokenProgramId = this.getTokenProgramForSpotMarket(spotMarketAccount); - const remainingAccounts = []; + const remainingAccounts: AccountMeta[] = []; this.addTokenMintToRemainingAccounts(spotMarketAccount, remainingAccounts); if (this.isTransferHook(spotMarketAccount)) { await this.addExtraAccountMetasToRemainingAccounts( @@ -10586,13 +10875,24 @@ export class DriftClient { spotMarketIndex: number, perpMarketIndex: number ): Promise { + const userAccount = this.getUserAccount(); + if (!userAccount) { + throw new Error( + `User account not found. Something is wrong with driftClient config` + ); + } const remainingAccounts = this.getRemainingAccounts({ - userAccounts: [this.getUserAccount()], + userAccounts: [userAccount], writablePerpMarketIndexes: [perpMarketIndex], writableSpotMarketIndexes: [spotMarketIndex], }); const spotMarket = this.getSpotMarketAccount(spotMarketIndex); + if (!spotMarket) { + throw new Error( + `Spot market account not found for index ${spotMarketIndex}` + ); + } const tokenProgramId = this.getTokenProgramForSpotMarket(spotMarket); return await this.program.instruction.resolvePerpPnlDeficit( @@ -10618,8 +10918,11 @@ export class DriftClient { userTokenAccountPublicKey: PublicKey ): Promise { const spotMarket = await this.getSpotMarketAccount(marketIndex); + if (!spotMarket) { + throw new Error(`Spot market account not found for index ${marketIndex}`); + } - const remainingAccounts = []; + const remainingAccounts: AccountMeta[] = []; this.addTokenMintToRemainingAccounts(spotMarket, remainingAccounts); if (this.isTransferHook(spotMarket)) { await this.addExtraAccountMetasToRemainingAccounts( @@ -10671,9 +10974,17 @@ export class DriftClient { public getPerpMarketExtendedInfo( marketIndex: number - ): PerpMarketExtendedInfo { + ): PerpMarketExtendedInfo | undefined { const marketAccount = this.getPerpMarketAccount(marketIndex); + if (!marketAccount) { + return undefined; + } const quoteAccount = this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX); + if (!quoteAccount) { + throw new Error( + `Quote spot market account not found. Something is wrong with driftClient config` + ); + } const extendedInfo: PerpMarketExtendedInfo = { marketIndex, @@ -10724,18 +11035,23 @@ export class DriftClient { feeTier.makerRebateNumerator / feeTier.makerRebateDenominator; if (marketIndex !== undefined) { - let marketAccount = null; + let marketAccount: + | null + | undefined + | PerpMarketAccount + | SpotMarketAccount = null; + let feeAdjustment = 1; if (isVariant(marketType, 'perp')) { marketAccount = this.getPerpMarketAccount(marketIndex); + feeAdjustment = marketAccount?.feeAdjustment ?? 0; } else { marketAccount = this.getSpotMarketAccount(marketIndex); } - - takerFee += (takerFee * marketAccount.feeAdjustment) / 100; + takerFee += (takerFee * feeAdjustment) / 100; if (userHLM) { takerFee *= 2; } - makerFee += (makerFee * marketAccount.feeAdjustment) / 100; + makerFee += (makerFee * feeAdjustment) / 100; } return { @@ -10786,7 +11102,9 @@ export class DriftClient { return this.receiverProgram; } - public async getSwitchboardOnDemandProgram(): Promise> { + public async getSwitchboardOnDemandProgram(): Promise< + Program30 | undefined + > { if (this.sbOnDemandProgram === undefined) { this.sbOnDemandProgram = await AnchorUtils.loadProgramFromConnection( this.connection @@ -11089,6 +11407,9 @@ export class DriftClient { numSignatures = 3 ): Promise { const program = await this.getSwitchboardOnDemandProgram(); + if (!program) { + return undefined; + } const feedAccount = new PullFeed(program, feed); if (!this.sbProgramFeedConfigs) { this.sbProgramFeedConfigs = new Map(); @@ -11117,7 +11438,7 @@ export class DriftClient { feed: PublicKey, recentSlothash?: Slothash, numSignatures = 3 - ): Promise { + ): Promise { const pullIx = await this.getPostSwitchboardOnDemandUpdateAtomicIx( feed, recentSlothash, @@ -11250,7 +11571,12 @@ export class DriftClient { const signingAuthority = overrides?.signingAuthority ?? this.wallet.publicKey; const userAccount = - overrides?.user.getUserAccount() ?? this.getUserAccount(subAccountId); + overrides?.user?.getUserAccount() ?? this.getUserAccount(subAccountId); + if (!userAccount) { + throw new Error( + `User account not found for subAccountId ${subAccountId}` + ); + } const remainingAccounts = this.getRemainingAccounts({ userAccounts: depositToTradeArgs?.isMakingNewAccount ? [] : [userAccount], @@ -11390,6 +11716,11 @@ export class DriftClient { spotMarketIndex: number ): Promise { const spotMarket = await this.getSpotMarketAccount(spotMarketIndex); + if (!spotMarket) { + throw new Error( + `Spot market account not found for index ${spotMarketIndex}` + ); + } return this.program.instruction.pauseSpotMarketDepositWithdraw({ accounts: { state: await this.getStatePublicKey(), @@ -11446,12 +11777,17 @@ export class DriftClient { data.set(oraclePrice.toArrayLike(Buffer, 'le', 8), 5); // next 8 bytes data.set(oracleSequenceId.toArrayLike(Buffer, 'le', 8), 13); // next 8 bytes + const perpMarket = this.getPerpMarketAccount(marketIndex); + if (!perpMarket) { + throw new Error(`Perp market account not found for index ${marketIndex}`); + } + // Build the instruction manually return new TransactionInstruction({ programId: this.program.programId, keys: [ { - pubkey: this.getPerpMarketAccount(marketIndex).pubkey, + pubkey: perpMarket.pubkey, isWritable: true, isSigner: false, }, @@ -11502,12 +11838,16 @@ export class DriftClient { data.set(discriminatorBuffer, 0); data.writeInt8(ammSpreadAdjustment, 5); // next byte + const perpMarket = this.getPerpMarketAccount(marketIndex); + if (!perpMarket) { + throw new Error(`Perp market account not found for index ${marketIndex}`); + } // Build the instruction manually return new TransactionInstruction({ programId: this.program.programId, keys: [ { - pubkey: this.getPerpMarketAccount(marketIndex).pubkey, + pubkey: perpMarket.pubkey, isWritable: true, isSigner: false, }, @@ -11676,12 +12016,17 @@ export class DriftClient { readablePerpMarketIndex: perpMarketIndexes, }); + const quoteMarket = this.getSpotMarketAccount(0); + if (!quoteMarket) { + throw new Error(`Quote spot market account not found for index 0`); + } + return this.program.instruction.updateAmmCache({ accounts: { state: await this.getStatePublicKey(), keeper: this.wallet.publicKey, ammCache: getAmmCachePublicKey(this.program.programId), - quoteMarket: this.getSpotMarketAccount(0).pubkey, + quoteMarket: quoteMarket.pubkey, }, remainingAccounts, }); @@ -11705,6 +12050,11 @@ export class DriftClient { constituent: ConstituentAccount ): Promise { const spotMarket = this.getSpotMarketAccount(constituent.spotMarketIndex); + if (!spotMarket) { + throw new Error( + `Spot market account not found for index ${constituent.spotMarketIndex}` + ); + } return this.program.instruction.updateConstituentOracleInfo({ accounts: { keeper: this.wallet.publicKey, @@ -11766,12 +12116,26 @@ export class DriftClient { lpPool, outMarketIndex ); + + const inSpotMarket = this.getSpotMarketAccount(inMarketIndex); + if (!inSpotMarket) { + throw new Error( + `Spot market account not found for index ${inMarketIndex}` + ); + } + const outSpotMarket = this.getSpotMarketAccount(outMarketIndex); + if (!outSpotMarket) { + throw new Error( + `Spot market account not found for index ${outMarketIndex}` + ); + } + const userInTokenAccount = await getAssociatedTokenAddress( - this.getSpotMarketAccount(inMarketIndex).mint, + inSpotMarket.mint, userAuthority ); const userOutTokenAccount = await getAssociatedTokenAddress( - this.getSpotMarketAccount(outMarketIndex).mint, + outSpotMarket.mint, userAuthority ); const inConstituent = getConstituentPublicKey( @@ -11784,8 +12148,8 @@ export class DriftClient { lpPool, outMarketIndex ); - const inMarketMint = this.getSpotMarketAccount(inMarketIndex).mint; - const outMarketMint = this.getSpotMarketAccount(outMarketIndex).mint; + const inMarketMint = inSpotMarket.mint; + const outMarketMint = outSpotMarket.mint; const constituentTargetBase = getConstituentTargetBasePublicKey( this.program.programId, @@ -11984,6 +12348,11 @@ export class DriftClient { }); const spotMarket = this.getSpotMarketAccount(inMarketIndex); + if (!spotMarket) { + throw new Error( + `Spot market account not found for index ${inMarketIndex}` + ); + } const inMarketMint = spotMarket.mint; const isSolMarket = inMarketMint.equals(WRAPPED_SOL_MINT); @@ -12199,6 +12568,11 @@ export class DriftClient { }); const spotMarket = this.getSpotMarketAccount(outMarketIndex); + if (!spotMarket) { + throw new Error( + `Spot market account not found for index ${outMarketIndex}` + ); + } const outMarketMint = spotMarket.mint; const outConstituent = getConstituentPublicKey( this.program.programId, @@ -12310,6 +12684,11 @@ export class DriftClient { }); const spotMarket = this.getSpotMarketAccount(outMarketIndex); + if (!spotMarket) { + throw new Error( + `Spot market account not found for index ${outMarketIndex}` + ); + } const outMarketMint = spotMarket.mint; const outConstituent = getConstituentPublicKey( this.program.programId, @@ -12544,11 +12923,11 @@ export class DriftClient { lpPoolId: number, perpMarketIndexes: number[] ): Promise { - const remainingAccounts = []; + const remainingAccounts: AccountMeta[] = []; remainingAccounts.push( ...perpMarketIndexes.map((index) => { return { - pubkey: this.getPerpMarketAccount(index).pubkey, + pubkey: this.getPerpMarketAccount(index)?.pubkey ?? PublicKey.default, isSigner: false, isWritable: true, }; @@ -12656,7 +13035,8 @@ export class DriftClient { txVersion: txVersion ?? this.txVersion, txParams: txParams ?? this.txParams, connection: this.connection, - preFlightCommitment: this.opts.preflightCommitment, + preFlightCommitment: + this.opts?.preflightCommitment ?? DEFAULT_COMMITMENT_LEVEL, fetchAllMarketLookupTableAccounts: this.fetchAllLookupTableAccounts.bind(this), lookupTables, @@ -12673,17 +13053,20 @@ export class DriftClient { lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean ): Promise<(Transaction | VersionedTransaction)[]> { - return this.txHandler.buildBulkTransactions({ + const txns = await this.txHandler.buildBulkTransactions({ instructions, txVersion: txVersion ?? this.txVersion, txParams: txParams ?? this.txParams, connection: this.connection, - preFlightCommitment: this.opts.preflightCommitment, + preFlightCommitment: + this.opts?.preflightCommitment ?? DEFAULT_COMMITMENT_LEVEL, fetchAllMarketLookupTableAccounts: this.fetchAllLookupTableAccounts.bind(this), lookupTables, forceVersionedTransaction, }); + + return txns.filter(Boolean) as (Transaction | VersionedTransaction)[]; } async buildTransactionsMap( @@ -12701,7 +13084,8 @@ export class DriftClient { txVersion: txVersion ?? this.txVersion, txParams: txParams ?? this.txParams, connection: this.connection, - preFlightCommitment: this.opts.preflightCommitment, + preFlightCommitment: + this.opts?.preflightCommitment ?? DEFAULT_COMMITMENT_LEVEL, fetchAllMarketLookupTableAccounts: this.fetchAllLookupTableAccounts.bind(this), lookupTables, @@ -12724,7 +13108,8 @@ export class DriftClient { txVersion: txVersion ?? this.txVersion, txParams: txParams ?? this.txParams, connection: this.connection, - preFlightCommitment: this.opts.preflightCommitment, + preFlightCommitment: + this.opts?.preflightCommitment ?? DEFAULT_COMMITMENT_LEVEL, fetchAllMarketLookupTableAccounts: this.fetchAllLookupTableAccounts.bind(this), lookupTables, diff --git a/sdk/src/markets.ts b/sdk/src/markets.ts new file mode 100644 index 000000000..298080f14 --- /dev/null +++ b/sdk/src/markets.ts @@ -0,0 +1,24 @@ +import { DriftEnv } from './config'; +import { SpotMarketConfig, SpotMarkets } from './constants'; +import { PerpMarketConfig, PerpMarkets } from './constants/perpMarkets'; +import { isOneOfVariant } from './types'; + +export const getActivePerpMarkets = ( + driftEnv: DriftEnv +): PerpMarketConfig[] => { + return PerpMarkets[driftEnv ?? 'mainnet-beta'].filter( + (market) => + !market.marketStatus || + !isOneOfVariant(market.marketStatus, ['delisted', 'settlement']) + ); +}; + +export const getActiveSpotMarkets = ( + driftEnv: DriftEnv +): SpotMarketConfig[] => { + return SpotMarkets[driftEnv ?? 'mainnet-beta'].filter( + (market) => + !market.marketStatus || + !isOneOfVariant(market.marketStatus, ['delisted', 'settlement']) + ); +}; diff --git a/sdk/src/types.ts b/sdk/src/types.ts index ea111ce0c..835fb402d 100644 --- a/sdk/src/types.ts +++ b/sdk/src/types.ts @@ -1315,7 +1315,7 @@ export type OptionalOrderParams = { export type ModifyOrderParams = { [Property in keyof OrderParams]?: OrderParams[Property] | null; -} & { policy?: ModifyOrderPolicy }; +} & { policy?: ModifyOrderPolicy | null }; export enum ModifyOrderPolicy { MustModify = 1,