Skip to Content

Users

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

// Assumes you already constructed and subscribed `driftClient`. const [txSig, userAccountPublicKey] = await driftClient.initializeUserAccount(0, "my-account"); console.log(txSig, userAccountPublicKey.toBase58());
Method DriftClient.initializeUserAccountReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
namestring
referrerInfoReferrerInfo
txParamsTxParams
Returns:
Promise<[string, PublicKey]>

Get the next subaccount id

const nextId = driftClient.getNextSubAccountId(); console.log(nextId);
Method DriftClient.getNextSubAccountIdReference ↗
Parameters:
This function does not accept any parameters.
Returns:
Promise<number>

Get a User and subscribe

import { User } from "@drift-labs/sdk"; const user = driftClient.getUser(); // convenience helper await user.subscribe();
Class UserReference ↗
NameTypeDefault
driftClientDriftClient
userAccountPublicKeyPublicKey
accountSubscriberUserAccountSubscriber
_isSubscribedboolean
eventEmitterStrictEventEmitter<EventEmitter, UserAccountEvents>
isSubscribedboolean
subscribe(userAccount?: UserAccount | undefined) => Promise<boolean>

Subscribe to User state accounts

fetchAccounts() => Promise<void>

Forces the accountSubscriber to fetch account updates from rpc

unsubscribe() => Promise<void>
getUserAccount() => UserAccount
forceGetUserAccount() => Promise<UserAccount>
getUserAccountAndSlot() => DataAndSlot<UserAccount> | undefined
getPerpPositionForUserAccount(userAccount: UserAccount, marketIndex: number) => PerpPosition | undefined
getPerpPosition(marketIndex: number) => PerpPosition | undefined

Gets the user’s current position for a given perp market. If the user has no position returns undefined

getPerpPositionOrEmpty(marketIndex: number) => PerpPosition
getPerpPositionAndSlot(marketIndex: number) => DataAndSlot<PerpPosition | undefined>
getSpotPositionForUserAccount(userAccount: UserAccount, marketIndex: number) => SpotPosition | undefined
getSpotPosition(marketIndex: number) => SpotPosition | undefined

Gets the user’s current position for a given spot market. If the user has no position returns undefined

getSpotPositionAndSlot(marketIndex: number) => DataAndSlot<SpotPosition | undefined>
getEmptySpotPosition(marketIndex: number) => SpotPosition
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.

getEmptyPosition(marketIndex: number) => PerpPosition
isPositionEmpty(position: PerpPosition) => boolean
getIsolatePerpPositionTokenAmount(perpMarketIndex: number) => BN
getClonedPosition(position: PerpPosition) => PerpPosition
getOrderForUserAccount(userAccount: UserAccount, orderId: number) => Order | undefined
getOrder(orderId: number) => Order | undefined
getOrderAndSlot(orderId: number) => DataAndSlot<Order | undefined>
getOrderByUserIdForUserAccount(userAccount: UserAccount, userOrderId: number) => Order | undefined
getOrderByUserOrderId(userOrderId: number) => Order | undefined
getOrderByUserOrderIdAndSlot(userOrderId: number) => DataAndSlot<Order | undefined>
getOpenOrdersForUserAccount(userAccount?: UserAccount | undefined) => Order[]
getOpenOrders() => Order[]
getOpenOrdersAndSlot() => DataAndSlot<Order[]>
getUserAccountPublicKey() => PublicKey
exists() => Promise<boolean>
getPerpBidAsks(marketIndex: number) => [BN, BN]

calculates the total open bids/asks in a perp market (including lps)

getPerpBuyingPower(marketIndex: number, collateralBuffer?: any, enterHighLeverageMode?: any, maxMarginRatio?: any, positionType?: "isolated" | "cross" | undefined) => BN

calculates Buying Power = free collateral / initial margin ratio

getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex: number, freeCollateral: BN, baseAssetAmount: BN, enterHighLeverageMode?: any, perpMarketMaxMarginRatio?: any) => BN
getFreeCollateral(marginCategory?: MarginCategory | undefined, enterHighLeverageMode?: boolean | undefined, perpMarketIndex?: number | undefined) => BN

calculates Free Collateral = Total collateral - margin requirement

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. Deprecated: Use the overload that includes { marginType, perpMarketIndex }

getInitialMarginRequirement(enterHighLeverageMode?: boolean | undefined, perpMarketIndex?: number | undefined) => BN
getMaintenanceMarginRequirement(liquidationBuffer?: any, perpMarketIndex?: number | undefined) => BN
getActivePerpPositionsForUserAccount(userAccount: UserAccount) => PerpPosition[]
getActivePerpPositions() => PerpPosition[]
getActivePerpPositionsAndSlot() => DataAndSlot<PerpPosition[]>
getActiveSpotPositionsForUserAccount(userAccount: UserAccount) => SpotPosition[]
getActiveSpotPositions() => SpotPosition[]
getActiveSpotPositionsAndSlot() => DataAndSlot<SpotPosition[]>
getUnrealizedPNL(withFunding?: boolean | undefined, marketIndex?: number | undefined, withWeightMarginCategory?: MarginCategory | undefined, strict?: boolean | undefined, liquidationBuffer?: any) => BN

calculates unrealized position price pnl

getUnrealizedFundingPNL(marketIndex?: number | undefined) => BN

calculates unrealized funding payment pnl

getFuelBonus(now: BN, includeSettled?: boolean | undefined, includeUnsettled?: boolean | undefined, givenUserStats?: UserStats | undefined) => { depositFuel: BN; borrowFuel: BN; positionFuel: BN; takerFuel: BN; makerFuel: BN; insuranceFuel: BN; }
getSpotMarketAssetAndLiabilityValue(marketIndex?: number | undefined, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => { ...; }
getSpotMarketLiabilityValue(marketIndex?: number | undefined, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => BN
getSpotLiabilityValue(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any) => BN
getSpotMarketAssetValue(marketIndex?: number | undefined, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => BN
getSpotAssetValue(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory | undefined) => BN
getSpotPositionValue(marketIndex: number, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, now?: any) => BN
getNetSpotMarketValue(withWeightMarginCategory?: MarginCategory | undefined) => BN
getTotalCollateral(marginCategory?: MarginCategory | undefined, strict?: boolean | undefined, includeOpenOrders?: boolean | undefined, liquidationBuffer?: any, perpMarketIndex?: number | undefined) => BN

calculates TotalCollateral: collateral + unrealized pnl

getLiquidationBuffer() => Map<number | "cross", BN>
getHealth(perpMarketIndex?: number | undefined) => number

calculates User Health by comparing total collateral and maint. margin requirement

calculateWeightedPerpPositionLiability(perpPosition: PerpPosition, marginCategory?: MarginCategory | undefined, liquidationBuffer?: any, includeOpenOrders?: boolean | undefined, strict?: boolean | undefined, enteringHighLeverage?: any) => BN
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

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

getPerpPositionValue(marketIndex: number, oraclePriceData: Pick<OraclePriceData, "price">, includeOpenOrders?: boolean | undefined) => BN

calculates position value based on oracle

getPerpLiabilityValue(marketIndex: number, oraclePriceData: OraclePriceData, includeOpenOrders?: boolean | undefined) => BN

calculates position liabiltiy value in margin system

getPositionSide(currentPosition: Pick<PerpPosition, "baseAssetAmount">) => PositionDirection | undefined
getPositionEstimatedExitPriceAndPnl(position: PerpPosition, amountToClose?: any, useAMMClose?: boolean | undefined) => [BN, BN]

calculates average exit price (optionally for closing up to 100% of position)

getLeverage(includeOpenOrders?: boolean | undefined, perpMarketIndex?: number | undefined) => BN

calculates current user leverage which is (total liability size) / (net asset value)

calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }: { perpLiabilityValue: BN; perpPnl: BN; spotAssetValue: BN; spotLiabilityValue: BN; }) => BN
getLeverageComponents(includeOpenOrders?: boolean | undefined, marginCategory?: MarginCategory | undefined, perpMarketIndex?: number | undefined) => { perpLiabilityValue: BN; perpPnl: BN; spotAssetValue: BN; spotLiabilityValue: BN; }
isDustDepositPosition(spotMarketAccount: SpotMarketAccount) => boolean
getSpotMarketAccountsWithDustPosition() => SpotMarketAccount[]
getTotalLiabilityValue(marginCategory?: MarginCategory | undefined) => BN
getTotalAssetValue(marginCategory?: MarginCategory | undefined) => BN
getNetUsdValue() => BN
getTotalAllTimePnl() => BN

Calculates the all time P&L of the user.

Net withdraws + Net spot market value + Net unrealized P&L -

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

getMaxLeverageForSpot(spotMarketIndex: number, direction: PositionDirection) => BN

calculates max allowable leverage exceeding hitting requirement category

getMarginRatio() => BN

calculates margin ratio: 1 / leverage

canBeLiquidated() => AccountLiquidatableStatus & { isolatedPositions: Map<number, AccountLiquidatableStatus>; }
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
isBeingLiquidated() => boolean
isCrossMarginBeingLiquidated() => boolean
canCrossMarginBeLiquidated(marginCalc?: MarginCalculation | undefined) => boolean

Returns true if cross margin is currently below maintenance requirement (no buffer).

hasIsolatedPositionBeingLiquidated() => boolean
isIsolatedPositionBeingLiquidated(perpMarketIndex: number) => boolean
getLiquidatableIsolatedPositions(marginCalc?: MarginCalculation | undefined) => number[]

Returns true if any isolated perp position is currently below its maintenance requirement (no buffer).

canIsolatedPositionMarginBeLiquidated(isolatedMarginCalculation: IsolatedMarginCalculation) => boolean
hasStatus(status: UserStatus) => boolean
isBankrupt() => boolean
isHighLeverageMode(marginCategory: MarginCategory) => boolean
needsToSettleFundingPayment() => boolean

Checks if any user position cumulative funding differs from respective market cumulative funding

spotLiquidationPrice(marketIndex: number, positionBaseSizeChange?: any) => BN

Calculate the liquidation price of a spot position

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

calculateEntriesEffectOnFreeCollateral(market: PerpMarketAccount, oraclePrice: BN, perpPosition: PerpPosition, positionBaseSizeChange: BN, estimatedEntryPrice: BN, includeOpenOrders: boolean, enteringHighLeverage?: any, marginCategory?: MarginCategory | undefined) => BN
calculateFreeCollateralDeltaForPerp(market: PerpMarketAccount, perpPosition: PerpPosition, positionBaseSizeChange: BN, oraclePrice: BN, marginCategory?: MarginCategory | undefined, includeOpenOrders?: boolean | undefined, enteringHighLeverage?: any) => any
calculateFreeCollateralDeltaForSpot(market: SpotMarketAccount, signedTokenAmount: BN, marginCategory?: MarginCategory | undefined) => BN
liquidationPriceAfterClose(positionMarketIndex: number, closeQuoteAmount: BN, estimatedEntryPrice?: any) => BN

Calculates the estimated liquidation price for a position after closing a quote amount of the position.

getMarginUSDCRequiredForTrade(targetMarketIndex: number, baseSize: BN, estEntryPrice?: any, perpMarketMaxMarginRatio?: number | undefined) => BN
getCollateralDepositRequiredForTrade(targetMarketIndex: number, baseSize: BN, collateralIndex: number, perpMarketMaxMarginRatio?: number | undefined) => BN
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
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.

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

cloneAndUpdateSpotPosition(position: SpotPosition, tokenAmount: BN, market: SpotMarketAccount) => SpotPosition
calculateSpotPositionFreeCollateralContribution(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice) => BN
calculateSpotPositionLeverageContribution(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice) => { totalAssetValue: BN; totalLiabilityValue: BN; }
accountLeverageAfterSwap({ inMarketIndex, outMarketIndex, inAmount, outAmount, }: { inMarketIndex: number; outMarketIndex: number; inAmount: BN; outAmount: BN; }) => BN

Estimates what the user leverage will be after swap

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

getUserFeeTier(marketType: MarketType, now?: any) => FeeTier
calculateFeeForQuoteAmount(quoteAmount: BN, marketIndex?: number | undefined, enteringHighLeverageMode?: boolean | undefined) => BN

Calculates how much perp fee will be taken for a given sized trade

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

canBypassWithdrawLimits(marketIndex: number) => { canBypass: boolean; netDeposits: BN; depositAmount: BN; maxDepositAmount: BN; }
canMakeIdle(slot: BN) => boolean
getSafestTiers() => { perpTier: number; spotTier: number; }
getPerpPositionHealth({ marginCategory, perpPosition, oraclePriceData, quoteOraclePriceData, includeOpenOrders, }: { marginCategory: MarginCategory; perpPosition: PerpPosition; oraclePriceData?: OraclePriceData; quoteOraclePriceData?: OraclePriceData; includeOpenOrders?: boolean; }) => HealthComponent
getHealthComponents({ marginCategory, }: { marginCategory: MarginCategory; }) => HealthComponents
getTotalPerpPositionValueExcludingMarketany

Get the total position value, excluding any position coming from the given target market

getMMOracleDataForPerpMarketany
getOracleDataForPerpMarketany
getOracleDataForSpotMarketany
getActivePositions() => { activePerpPositions: number[]; activeSpotPositions: number[]; }

Get the active perp and spot positions of the user.

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.

isPerpPositionIsolated(perpPosition: PerpPosition) => boolean
const user = driftClient.getUser(); // active subaccount
Method DriftClient.getUserReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
authorityPublicKey
Returns:
User
// Fetch a specific subaccount. const user = driftClient.getUser(1);
Method DriftClient.getUserReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
authorityPublicKey
Returns:
User
const account = driftClient.getUser().getUserAccount(); console.log(account);
Method User.getUserAccountReference ↗
Parameters:
This function does not accept any parameters.
Returns:
UserAccount
const account = driftClient.getUserAccount(); // active subaccount console.log(account);
Method DriftClient.getUserAccountReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
authorityPublicKey
Returns:
UserAccount | undefined
const user = driftClient.getUser(0); await user.fetchAccounts();
Method User.fetchAccountsReference ↗
Parameters:
This function does not accept any parameters.
Returns:
Promise<void>

Derived addresses (user account)

const userAccountPublicKey = await driftClient.getUserAccountPublicKey(0); console.log(userAccountPublicKey.toBase58());
Method DriftClient.getUserAccountPublicKeyReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
authorityPublicKey
Returns:
Promise<PublicKey>

Query user state (orders / positions)

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 ↗
Parameters:
NameTypeDefault
marketIndexnumber
Returns:
BN
const position = driftClient.getUser().getPerpPosition(0); console.log(position?.baseAssetAmount.toString());
Method User.getPerpPositionReference ↗
Parameters:
NameTypeDefault
marketIndexnumber
Returns:
PerpPosition | undefined
const order = driftClient.getUser().getOrder(1); console.log(order);
Method User.getOrderReference ↗
Parameters:
NameTypeDefault
orderIdnumber
Returns:
Order | undefined
const order = driftClient.getUser().getOrderByUserOrderId(1); console.log(order);
Method User.getOrderByUserOrderIdReference ↗
Parameters:
NameTypeDefault
userOrderIdnumber
Returns:
Order | undefined
const orders = driftClient.getUser().getOpenOrders(); console.log(orders.length);
Method User.getOpenOrdersReference ↗
Parameters:
This function does not accept any parameters.
Returns:
Order[]

Switch active subaccount

// Switch to subaccount 1. driftClient.switchActiveUser(1);
Method DriftClient.switchActiveUserReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
authorityPublicKey
Returns:
Promise<void>

Update user settings (delegate / margin)

import { PublicKey } from "@solana/web3.js"; await driftClient.updateUserDelegate(new PublicKey("<DELEGATE_PUBKEY>"), 0);
Method DriftClient.updateUserDelegateReference ↗
Parameters:
NameTypeDefault
delegatePublicKey
subAccountIdnumber
Returns:
Promise<string>
await driftClient.updateUserMarginTradingEnabled(true, 0);
Method DriftClient.updateUserMarginTradingEnabledReference ↗
Parameters:
NameTypeDefault
updates{ marginTradingEnabled: boolean; subAccountId: number; }[]
Returns:
Promise<string>
import { MARGIN_PRECISION } from "@drift-labs/sdk"; await driftClient.updateUserCustomMarginRatio([ { marginRatio: MARGIN_PRECISION, subAccountId: 0 }, ]);
Method DriftClient.updateUserCustomMarginRatioReference ↗
Parameters:
NameTypeDefault
updates{ marginRatio: number; subAccountId: number; }[]
txParamsTxParams
Returns:
Promise<string>

Delete a user account

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

await driftClient.deleteUser(1);
Method DriftClient.deleteUserReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
txParamsTxParams
Returns:
Promise<string>
Last updated on