Skip to Content

Users

How it works

A user account is the onchain account that holds your positions, orders, and collateral on Drift. Each wallet can create multiple user accounts (called subaccounts), identified by a numeric ID (0, 1, 2, etc.). All subaccounts under the same wallet share cross-margin, meaning collateral and risk are calculated across all of them together.

User accounts store your perp positions (long/short), spot balances (deposits/borrows), open orders, and leverage settings. When you interact with Drift (place orders, deposit, trade), you’re modifying data in your user account. The account is a Solana PDA (Program Derived Address) owned by the Drift program.

Subaccounts are useful for separating strategies, isolating risk between different trading styles, or delegating specific accounts to bots while keeping others manual. You can switch between subaccounts using the SDK, and each one maintains its own positions and orders while sharing the wallet’s overall collateral pool.

SDK Usage

Most write actions in Drift are done through DriftClient. For account-level reads (positions, orders, health), you’ll typically use a User.

Initialize a User Account

Create a new Drift user subaccount (PDA) for your wallet and return the transaction signature + user account address.

// Assumes you already constructed and subscribed `driftClient`. const [txSig, userAccountPublicKey] = await driftClient.initializeUserAccount(0, "my-account"); console.log(txSig, userAccountPublicKey.toBase58());
Method DriftClient.initializeUserAccountReference ↗
ParameterTypeRequired
subAccountId
number
No
name
string
No
referrerInfo
ReferrerInfo
No
txParams
TxParams
No
Returns
Promise<[string, PublicKey]>

Get the Next Subaccount ID

Return the next available subaccount ID for this client instance.

const nextId = driftClient.getNextSubAccountId(); console.log(nextId);
Method DriftClient.getNextSubAccountIdReference ↗
Returns
Promise<number>

Get a User and Subscribe

Import the User class and subscribe to account updates for a specific user instance.

import { User } from "@drift-labs/sdk"; const user = driftClient.getUser(); await user.subscribe();
Class UserReference ↗
PropertyTypeRequired
driftClient
DriftClient
Yes
userAccountPublicKey
PublicKey
Yes
accountSubscriber
UserAccountSubscriber
Yes
_isSubscribed
boolean
Yes
eventEmitter
StrictEventEmitter<EventEmitter, UserAccountEvents>
Yes
isSubscribed
boolean
Yes
subscribe
(userAccount?: UserAccount | undefined) => Promise<boolean>
Subscribe to User state accounts
Yes
fetchAccounts
() => Promise<void>
Forces the accountSubscriber to fetch account updates from rpc
Yes
unsubscribe
() => Promise<void>
Yes
getUserAccount
() => UserAccount
Yes
forceGetUserAccount
() => Promise<UserAccount>
Yes
getUserAccountAndSlot
() => DataAndSlot<UserAccount> | undefined
Yes
getPerpPositionForUserAccount
(userAccount: UserAccount, marketIndex: number) => PerpPosition | undefined
Yes
getPerpPosition
(marketIndex: number) => PerpPosition | undefined
Gets the user's current position for a given perp market. If the user has no position returns undefined
Yes
getPerpPositionOrEmpty
(marketIndex: number) => PerpPosition
Yes
getPerpPositionAndSlot
(marketIndex: number) => DataAndSlot<PerpPosition | undefined>
Yes
getSpotPositionForUserAccount
(userAccount: UserAccount, marketIndex: number) => SpotPosition | undefined
Yes
getSpotPosition
(marketIndex: number) => SpotPosition | undefined
Gets the user's current position for a given spot market. If the user has no position returns undefined
Yes
getSpotPositionAndSlot
(marketIndex: number) => DataAndSlot<SpotPosition | undefined>
Yes
getEmptySpotPosition
(marketIndex: number) => SpotPosition
Yes
getTokenAmount
(marketIndex: number) => BN
Returns the token amount for a given market. The spot market precision is based on the token mint decimals. Positive if it is a deposit, negative if it is a borrow.
Yes
getEmptyPosition
(marketIndex: number) => PerpPosition
Yes
isPositionEmpty
(position: PerpPosition) => boolean
Yes
getIsolatePerpPositionTokenAmount
(perpMarketIndex: number) => BN
Yes
getClonedPosition
(position: PerpPosition) => PerpPosition
Yes
getOrderForUserAccount
(userAccount: UserAccount, orderId: number) => Order | undefined
Yes
getOrder
(orderId: number) => Order | undefined
Yes
getOrderAndSlot
(orderId: number) => DataAndSlot<Order | undefined>
Yes
getOrderByUserIdForUserAccount
(userAccount: UserAccount, userOrderId: number) => Order | undefined
Yes
getOrderByUserOrderId
(userOrderId: number) => Order | undefined
Yes
getOrderByUserOrderIdAndSlot
(userOrderId: number) => DataAndSlot<Order | undefined>
Yes
getOpenOrdersForUserAccount
(userAccount?: UserAccount | undefined) => Order[]
Yes
getOpenOrders
() => Order[]
Yes
getOpenOrdersAndSlot
() => DataAndSlot<Order[]>
Yes
getUserAccountPublicKey
() => PublicKey
Yes
exists
() => Promise<boolean>
Yes
getPerpBidAsks
(marketIndex: number) => [BN, BN]
calculates the total open bids/asks in a perp market (including lps)
Yes
getPerpBuyingPower
(marketIndex: number, collateralBuffer?: any, enterHighLeverageMode?: any, maxMarginRatio?: any, positionType?: "isolated" | "cross" | undefined) => BN
calculates Buying Power = free collateral / initial margin ratio
Yes
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount
(marketIndex: number, freeCollateral: BN, baseAssetAmount: BN, enterHighLeverageMode?: any, perpMarketMaxMarginRatio?: any) => BN
Yes
getFreeCollateral
(marginCategory?: MarginCategory | undefined, enterHighLeverageMode?: boolean | undefined, perpMarketIndex?: number | undefined) => BN
calculates Free Collateral = Total collateral - margin requirement
Yes
getMarginRequirement
{ (marginCategory: MarginCategory, liquidationBuffer?: any, strict?: boolean | undefined, includeOpenOrders?: boolean | undefined, enteringHighLeverage?: boolean | undefined): BN; (marginCategory: MarginCategory, liquidationBuffer?: any, strict?: boolean | undefined, includeOpenOrders?: boolean | undefined, entering...
Calculates the margin requirement based on the specified parameters.
Yes
getInitialMarginRequirement
(enterHighLeverageMode?: boolean | undefined, perpMarketIndex?: number | undefined) => BN
Yes
getMaintenanceMarginRequirement
(liquidationBuffer?: any, perpMarketIndex?: number | undefined) => BN
Yes
getActivePerpPositionsForUserAccount
(userAccount: UserAccount) => PerpPosition[]
Yes
getActivePerpPositions
() => PerpPosition[]
Yes
getActivePerpPositionsAndSlot
() => DataAndSlot<PerpPosition[]>
Yes
getActiveSpotPositionsForUserAccount
(userAccount: UserAccount) => SpotPosition[]
Yes
getActiveSpotPositions
() => SpotPosition[]
Yes
getActiveSpotPositionsAndSlot
() => DataAndSlot<SpotPosition[]>
Yes
getUnrealizedPNL
(withFunding?: boolean | undefined, marketIndex?: number | undefined, withWeightMarginCategory?: MarginCategory | undefined, strict?: boolean | undefined, liquidationBuffer?: any) => BN
calculates unrealized position price pnl
Yes
getUnrealizedFundingPNL
(marketIndex?: number | undefined) => BN
calculates unrealized funding payment pnl
Yes
getFuelBonus
(now: BN, includeSettled?: boolean | undefined, includeUnsettled?: boolean | undefined, givenUserStats?: UserStats | undefined) => { depositFuel: BN; borrowFuel: BN; positionFuel: BN; takerFuel: BN; makerFuel: BN; insuranceFuel: BN; }
Yes
getSpotMarketAssetAndLiabilityValue
(marketIndex?: number | undefined, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => { ...; }
Yes
getSpotMarketLiabilityValue
(marketIndex?: number | undefined, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => BN
Yes
getSpotLiabilityValue
(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any) => BN
Yes
getSpotMarketAssetValue
(marketIndex?: number | undefined, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => BN
Yes
getSpotAssetValue
(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory | undefined) => BN
Yes
getSpotPositionValue
(marketIndex: number, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => BN
Yes
getNetSpotMarketValue
(withWeightMarginCategory?: MarginCategory | undefined) => BN
Yes
getTotalCollateral
(marginCategory?: MarginCategory | undefined, strict?: boolean | undefined, includeOpenOrders?: boolean | undefined, liquidationBuffer?: any, perpMarketIndex?: number | undefined) => BN
calculates TotalCollateral: collateral + unrealized pnl
Yes
getLiquidationBuffer
() => Map<number | "cross", BN>
Yes
getHealth
(perpMarketIndex?: number | undefined) => number
calculates User Health by comparing total collateral and maint. margin requirement
Yes
calculateWeightedPerpPositionLiability
(perpPosition: PerpPosition, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, enteringHighLeverage?: any) => BN
Yes
getPerpMarketLiabilityValue
(marketIndex: number, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined) => BN
calculates position value of a single perp market in margin system
Yes
getTotalPerpPositionLiability
(marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, enteringHighLeverage?: any) => BN
calculates sum of position value across all positions in margin system
Yes
getPerpPositionValue
(marketIndex: number, oraclePriceData: Pick<OraclePriceData, "price">, includeOpenOrders?: boolean | undefined) => BN
calculates position value based on oracle
Yes
getPerpLiabilityValue
(marketIndex: number, oraclePriceData: OraclePriceData, includeOpenOrders?: boolean | undefined) => BN
calculates position liabiltiy value in margin system
Yes
getPositionSide
(currentPosition: Pick<PerpPosition, "baseAssetAmount">) => PositionDirection | undefined
Yes
getPositionEstimatedExitPriceAndPnl
(position: PerpPosition, amountToClose?: any, useAMMClose?: boolean | undefined) => [BN, BN]
calculates average exit price (optionally for closing up to 100% of position)
Yes
getLeverage
(includeOpenOrders?: boolean | undefined, perpMarketIndex?: number | undefined) => BN
calculates current user leverage which is (total liability size) / (net asset value)
Yes
calculateLeverageFromComponents
({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }: { perpLiabilityValue: BN; perpPnl: BN; spotAssetValue: BN; spotLiabilityValue: BN; }) => BN
Yes
getLeverageComponents
(includeOpenOrders?: boolean | undefined, marginCategory?: MarginCategory | undefined, perpMarketIndex?: number | undefined) => { perpLiabilityValue: BN; perpPnl: BN; spotAssetValue: BN; spotLiabilityValue: BN; }
Yes
isDustDepositPosition
(spotMarketAccount: SpotMarketAccount) => boolean
Yes
getSpotMarketAccountsWithDustPosition
() => SpotMarketAccount[]
Yes
getTotalLiabilityValue
(marginCategory?: MarginCategory | undefined) => BN
Yes
getTotalAssetValue
(marginCategory?: MarginCategory | undefined) => BN
Yes
getNetUsdValue
() => BN
Yes
getTotalAllTimePnl
() => BN
Calculates the all time P&L of the user. Net withdraws + Net spot market value + Net unrealized P&L -
Yes
getMaxLeverageForPerp
(perpMarketIndex: number, _marginCategory?: MarginCategory | undefined, isLp?: boolean | undefined, enterHighLeverageMode?: any) => BN
calculates max allowable leverage exceeding hitting requirement category for large sizes where imf factor activates, result is a lower bound
Yes
getMaxLeverageForSpot
(spotMarketIndex: number, direction: PositionDirection) => BN
calculates max allowable leverage exceeding hitting requirement category
Yes
getMarginRatio
() => BN
calculates margin ratio: 1 / leverage
Yes
canBeLiquidated
() => AccountLiquidatableStatus & { isolatedPositions: Map<number, AccountLiquidatableStatus>; }
Yes
getLiquidationStatuses
(marginCalc?: MarginCalculation | undefined) => Map<number | "cross", AccountLiquidatableStatus>
New API: Returns liquidation status for cross and each isolated perp position. Map keys: - 'cross' for cross margin - marketIndex (number) for each isolated perp position
Yes
isBeingLiquidated
() => boolean
Yes
isCrossMarginBeingLiquidated
() => boolean
Yes
canCrossMarginBeLiquidated
(marginCalc?: MarginCalculation | undefined) => boolean
Returns true if cross margin is currently below maintenance requirement (no buffer).
Yes
hasIsolatedPositionBeingLiquidated
() => boolean
Yes
isIsolatedPositionBeingLiquidated
(perpMarketIndex: number) => boolean
Yes
getLiquidatableIsolatedPositions
(marginCalc?: MarginCalculation | undefined) => number[]
Returns true if any isolated perp position is currently below its maintenance requirement (no buffer).
Yes
canIsolatedPositionMarginBeLiquidated
(isolatedMarginCalculation: IsolatedMarginCalculation) => boolean
Yes
hasStatus
(status: UserStatus) => boolean
Yes
isBankrupt
() => boolean
Yes
isHighLeverageMode
(marginCategory: MarginCategory) => boolean
Yes
needsToSettleFundingPayment
() => boolean
Checks if any user position cumulative funding differs from respective market cumulative funding
Yes
spotLiquidationPrice
(marketIndex: number, positionBaseSizeChange?: any) => BN
Calculate the liquidation price of a spot position
Yes
liquidationPrice
(marketIndex: number, positionBaseSizeChange?: any, estimatedEntryPrice?: any, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, offsetCollateral?: any, enteringHighLeverage?: boolean | undefined, marginType?: MarginType | undefined) => BN
Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
Yes
calculateEntriesEffectOnFreeCollateral
(market: PerpMarketAccount, oraclePrice: BN, perpPosition: PerpPosition, positionBaseSizeChange: BN, estimatedEntryPrice: BN, includeOpenOrders: boolean, enteringHighLeverage?: any, marginCategory?: MarginCategory | undefined) => BN
Yes
calculateFreeCollateralDeltaForPerp
(market: PerpMarketAccount, perpPosition: PerpPosition, positionBaseSizeChange: BN, oraclePrice: BN, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, enteringHighLeverage?: any) => any
Yes
calculateFreeCollateralDeltaForSpot
(market: SpotMarketAccount, signedTokenAmount: BN, marginCategory?: MarginCategory | undefined) => BN
Yes
liquidationPriceAfterClose
(positionMarketIndex: number, closeQuoteAmount: BN, estimatedEntryPrice?: any) => BN
Calculates the estimated liquidation price for a position after closing a quote amount of the position.
Yes
getMarginUSDCRequiredForTrade
(targetMarketIndex: number, baseSize: BN, estEntryPrice?: any, perpMarketMaxMarginRatio?: number | undefined) => BN
Yes
getCollateralDepositRequiredForTrade
(targetMarketIndex: number, baseSize: BN, collateralIndex: number, perpMarketMaxMarginRatio?: number | undefined) => BN
Yes
getMaxTradeSizeUSDCForPerp
(targetMarketIndex: number, tradeSide: PositionDirection, isLp?: boolean | undefined, enterHighLeverageMode?: any, maxMarginRatio?: any, positionType?: "isolated" | "cross" | undefined) => { ...; }
Separates the max trade size into two parts: - tradeSize: The maximum trade size for target direction - oppositeSideTradeSize: the trade size for closing the opposite direction
Yes
getMaxTradeSizeUSDCForSpot
(targetMarketIndex: number, direction: PositionDirection, currentQuoteAssetValue?: any, currentSpotMarketNetValue?: any) => BN
Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
Yes
getMaxSwapAmount
({ inMarketIndex, outMarketIndex, calculateSwap, iterationLimit, }: { inMarketIndex: number; outMarketIndex: number; calculateSwap?: (inAmount: BN) => BN; iterationLimit?: number; }) => { inAmount: BN; outAmount: BN; leverage: BN; }
Calculates the max amount of token that can be swapped from inMarket to outMarket Assumes swap happens at oracle price
Yes
cloneAndUpdateSpotPosition
(position: SpotPosition, tokenAmount: BN, market: SpotMarketAccount) => SpotPosition
Yes
calculateSpotPositionFreeCollateralContribution
(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice) => BN
Yes
calculateSpotPositionLeverageContribution
(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice) => { totalAssetValue: BN; totalLiabilityValue: BN; }
Yes
accountLeverageAfterSwap
({ inMarketIndex, outMarketIndex, inAmount, outAmount, }: { inMarketIndex: number; outMarketIndex: number; inAmount: BN; outAmount: BN; }) => BN
Estimates what the user leverage will be after swap
Yes
accountLeverageRatioAfterTrade
(targetMarketIndex: number, targetMarketType: MarketType, tradeQuoteAmount: BN, tradeSide: PositionDirection, includeOpenOrders?: boolean | undefined) => BN
Returns the leverage ratio for the account after adding (or subtracting) the given quote size to the given position
Yes
getUserFeeTier
(marketType: MarketType, now?: any) => FeeTier
Yes
calculateFeeForQuoteAmount
(quoteAmount: BN, marketIndex?: number | undefined, enteringHighLeverageMode?: boolean | undefined) => BN
Calculates how much perp fee will be taken for a given sized trade
Yes
getWithdrawalLimit
(marketIndex: number, reduceOnly?: boolean | undefined) => BN
Calculates a user's max withdrawal amounts for a spot market. If reduceOnly is true, it will return the max withdrawal amount without opening a liability for the user
Yes
canBypassWithdrawLimits
(marketIndex: number) => { canBypass: boolean; netDeposits: BN; depositAmount: BN; maxDepositAmount: BN; }
Yes
canMakeIdle
(slot: BN) => boolean
Yes
getSafestTiers
() => { perpTier: number; spotTier: number; }
Yes
getPerpPositionHealth
({ marginCategory, perpPosition, oraclePriceData, quoteOraclePriceData, includeOpenOrders, }: { marginCategory: MarginCategory; perpPosition: PerpPosition; oraclePriceData?: OraclePriceData; quoteOraclePriceData?: OraclePriceData; includeOpenOrders?: boolean; }) => HealthComponent
Yes
getHealthComponents
({ marginCategory, }: { marginCategory: MarginCategory; }) => HealthComponents
Yes
getTotalPerpPositionValueExcludingMarket
any
Get the total position value, excluding any position coming from the given target market
Yes
getMMOracleDataForPerpMarket
any
Yes
getOracleDataForPerpMarket
any
Yes
getOracleDataForSpotMarket
any
Yes
getActivePositions
() => { activePerpPositions: number[]; activeSpotPositions: number[]; }
Get the active perp and spot positions of the user.
Yes
getMarginCalculation
(marginCategory?: MarginCategory | undefined, opts?: { strict?: boolean; includeOpenOrders?: boolean; enteringHighLeverage?: boolean; liquidationBufferMap?: Map<number | "cross", BN>; } | undefined) => MarginCalculation
Compute the full margin calculation for the user's account. Prioritize using this function instead of calling getMarginRequirement or getTotalCollateral multiple times. Consumers can use this to avoid duplicating work across separate calls.
Yes
isPerpPositionIsolated
(perpPosition: PerpPosition) => boolean
Yes

Get active subaccount user

Get the User object for the currently active subaccount.

const user = driftClient.getUser();
Method DriftClient.getUserReference ↗
ParameterTypeRequired
subAccountId
number
No
authority
PublicKey
No
Returns
User

Get a specific subaccount user

Get the User object for a specific subaccount ID.

const user = driftClient.getUser(1);
Method DriftClient.getUserReference ↗
ParameterTypeRequired
subAccountId
number
No
authority
PublicKey
No
Returns
User

Read account via User

Read raw onchain UserAccount data from a User instance.

const account = driftClient.getUser().getUserAccount(); console.log(account);
Method User.getUserAccountReference ↗
Returns
UserAccount

Read account via DriftClient

Read raw onchain UserAccount data directly from DriftClient for the active subaccount.

const account = driftClient.getUserAccount(); console.log(account);
Method DriftClient.getUserAccountReference ↗
ParameterTypeRequired
subAccountId
number
No
authority
PublicKey
No
Returns
UserAccount | undefined

Refresh user accounts

Force-refresh subscribed user-related accounts from RPC.

const user = driftClient.getUser(0); await user.fetchAccounts();
Method User.fetchAccountsReference ↗
Returns
Promise<void>

Derived Addresses (User Account)

User accounts are Program Derived Addresses (PDAs) - deterministic addresses generated from seeds (the program ID, wallet authority, and subaccount ID). PDAs are a Solana concept that lets you calculate an account’s address without making an RPC call.

This is useful when you need to reference a user account address before fetching it, such as when constructing transactions or querying multiple accounts in parallel.

For a deeper understanding of PDAs and program structure, see Program Structure.

Derive the user account PDA for a given subaccount without an RPC fetch.

const userAccountPublicKey = await driftClient.getUserAccountPublicKey(0); console.log(userAccountPublicKey.toBase58());
Method DriftClient.getUserAccountPublicKeyReference ↗
ParameterTypeRequired
subAccountId
number
No
authority
PublicKey
No
Returns
Promise<PublicKey>

Query User State (Orders / Positions)

Get token amount (deposit vs borrow)

Return your token balance for a spot market as a signed value (+ deposit, - borrow).

import { BN } from "@drift-labs/sdk"; const user = driftClient.getUser(); const tokenAmount = user.getTokenAmount(0); const isDeposit = tokenAmount.gte(new BN(0)); const isBorrow = tokenAmount.lt(new BN(0)); console.log({ tokenAmount: tokenAmount.toString(), isDeposit, isBorrow });
Method User.getTokenAmountReference ↗
ParameterTypeRequired
marketIndex
number
Yes
Returns
BN

Get a perp position

Get your perp position record for a market index (or undefined if no position exists).

const position = driftClient.getUser().getPerpPosition(0); console.log(position?.baseAssetAmount.toString());
Method User.getPerpPositionReference ↗
ParameterTypeRequired
marketIndex
number
Yes
Returns
PerpPosition | undefined

Get an order by order id

Look up a specific order using its internal Drift orderId.

const order = driftClient.getUser().getOrder(1); console.log(order);
Method User.getOrderReference ↗
ParameterTypeRequired
orderId
number
Yes
Returns
Order | undefined

Get an order by user order id

Look up a specific order using your custom userOrderId.

const order = driftClient.getUser().getOrderByUserOrderId(1); console.log(order);
Method User.getOrderByUserOrderIdReference ↗
ParameterTypeRequired
userOrderId
number
Yes
Returns
Order | undefined

Get all open orders

Return all currently open (unfilled/uncancelled) orders for this user.

const orders = driftClient.getUser().getOpenOrders(); console.log(orders.length);
Method User.getOpenOrdersReference ↗
Returns
Order[]

Active Subaccount

The active subaccount is the default subaccount that DriftClient methods operate on when you don’t explicitly specify a subaccount ID. By default, the active subaccount is 0.

Many SDK methods use the active subaccount implicitly:

  • driftClient.getUser() - returns the User for the active subaccount
  • driftClient.getUserAccount() - returns the account data for the active subaccount
  • driftClient.placePerpOrder(orderParams) - places an order on the active subaccount
  • driftClient.getSpotPosition(marketIndex) - gets position from the active subaccount
  • driftClient.getPerpPosition(marketIndex) - gets position from the active subaccount

You can change which subaccount is active using switchActiveUser(), or you can explicitly pass a subaccount ID to methods that support it (like getUser(subAccountId)).

Switch Active Subaccount

Change the active subaccount context used by default in DriftClient methods.

// Switch to subaccount 1. await driftClient.switchActiveUser(1);
Method DriftClient.switchActiveUserReference ↗
ParameterTypeRequired
subAccountId
number
Yes
authority
PublicKey
No
Returns
Promise<void>

Update Delegate

A delegate is another wallet that can trade on behalf of your user account without being able to withdraw funds. This is useful for allowing trading bots to manage positions while keeping withdrawal authority secure.

Learn more: Delegated Accounts

Set or update the delegate authority allowed to trade on a subaccount.

import { PublicKey } from "@solana/web3.js"; await driftClient.updateUserDelegate(new PublicKey("<DELEGATE_PUBKEY>"), 0);
Method DriftClient.updateUserDelegateReference ↗
ParameterTypeRequired
delegate
PublicKey
Yes
subAccountId
number
No
Returns
Promise<string>

Update Margin Settings

Margin trading settings control how your account can use leverage and borrow against collateral. You can enable/disable margin trading or set custom margin ratios to control risk.

Learn more: Margin

Enable or disable margin trading permissions for one or more subaccounts.

await driftClient.updateUserMarginTradingEnabled([ { marginTradingEnabled: true, subAccountId: 0 }, ]);
Method DriftClient.updateUserMarginTradingEnabledReference ↗
ParameterTypeRequired
updates
{ marginTradingEnabled: boolean; subAccountId: number; }[]
Yes
Returns
Promise<string>

Set a custom margin ratio cap for one or more subaccounts.

// marginRatio is a number scaled by 10000 (MARGIN_PRECISION) // e.g. 10000 = 1x max leverage, 5000 = 2x, 2000 = 5x await driftClient.updateUserCustomMarginRatio([ { marginRatio: 5000, subAccountId: 0 }, // 2x max leverage ]);
Method DriftClient.updateUserCustomMarginRatioReference ↗
ParameterTypeRequired
updates
{ marginRatio: number; subAccountId: number; }[]
Yes
txParams
TxParams
No
Returns
Promise<string>

Delete a User Account

If a subaccount has no assets/liabilities, it can be deleted to reclaim rent.

Delete an empty subaccount and close its user account.

await driftClient.deleteUser(1);
Method DriftClient.deleteUserReference ↗
ParameterTypeRequired
subAccountId
number
No
txParams
TxParams
No
Returns
Promise<string>
Last updated on