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 ↗| Name | Type | Default |
|---|---|---|
subAccountId | number | |
name | string | |
referrerInfo | ReferrerInfo | |
txParams | TxParams |
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 ↗| Name | Type | Default |
|---|---|---|
subAccountId | number | |
authority | 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 subaccountdriftClient.getUserAccount()- returns the account data for the active subaccountdriftClient.placePerpOrder(orderParams)- places an order on the active subaccountdriftClient.getSpotPosition(marketIndex)- gets position from the active subaccountdriftClient.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 ↗| Name | Type | Default |
|---|---|---|
subAccountId | number | |
authority | PublicKey |
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 ↗| Name | Type | Default |
|---|---|---|
delegate | PublicKey | |
subAccountId | number |
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 ↗| Name | Type | Default |
|---|---|---|
updates | { marginTradingEnabled: boolean; subAccountId: number; }[] |
// 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 ↗| Name | Type | Default |
|---|---|---|
updates | { marginRatio: number; subAccountId: number; }[] | |
txParams | TxParams |
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 ↗| Name | Type | Default |
|---|---|---|
subAccountId | number | |
txParams | TxParams |