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

// 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);

Get a User and Subscribe

View User import

import { User } from "@drift-labs/sdk"; const user = driftClient.getUser(); await user.subscribe();

Get active subaccount user

const user = driftClient.getUser();

Get a specific subaccount user

const user = driftClient.getUser(1);

Read account via User

const account = driftClient.getUser().getUserAccount(); console.log(account);

Read account via DriftClient

const account = driftClient.getUserAccount(); console.log(account);

Refresh user accounts

const user = driftClient.getUser(0); await user.fetchAccounts();

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.

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)

Get token amount (deposit vs 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 });

Get a perp position

const position = driftClient.getUser().getPerpPosition(0); console.log(position?.baseAssetAmount.toString());

Get an order by order id

const order = driftClient.getUser().getOrder(1); console.log(order);

Get an order by user order id

const order = driftClient.getUser().getOrderByUserOrderId(1); console.log(order);

Get all open orders

const orders = driftClient.getUser().getOpenOrders(); console.log(orders.length);

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

// Switch to subaccount 1. await driftClient.switchActiveUser(1);
Method DriftClient.switchActiveUserReference ↗
Parameters:
NameTypeDefault
subAccountIdnumber
authorityPublicKey
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

import { PublicKey } from "@solana/web3.js"; await driftClient.updateUserDelegate(new PublicKey("<DELEGATE_PUBKEY>"), 0);
Method DriftClient.updateUserDelegateReference ↗
Parameters:
NameTypeDefault
delegatePublicKey
subAccountIdnumber
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

await driftClient.updateUserMarginTradingEnabled([ { marginTradingEnabled: true, subAccountId: 0 }, ]);
Method DriftClient.updateUserMarginTradingEnabledReference ↗
Parameters:
NameTypeDefault
updates{ marginTradingEnabled: boolean; subAccountId: number; }[]
Returns:
Promise<string>
// 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 ↗
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