Transfers
Transfers let you move balances and positions between subaccounts owned by the same authority.
Why Use Subaccount Transfers?
Subaccounts let you isolate risk and organize trading strategies. Common use cases for transfers include:
- Strategy isolation: Separate market making from directional trading to prevent one strategy’s losses from affecting another’s collateral
- Risk management: Move profits from an active trading account to a safer holding account
- Rebalancing: Redistribute collateral when one subaccount needs more margin
- Bot separation: Isolate automated trading bots on separate subaccounts while keeping manual trades separate
- Experimentation: Test new strategies on a subaccount with limited capital, then transfer funds if successful
All subaccounts under the same wallet share cross-margin, but transfers let you explicitly move balances and positions to reorganize your capital.
SDK Usage
Transfer a Spot Deposit Between Subaccounts
const marketIndex = 0; // e.g. USDC
const amount = velocityClient.convertToSpotPrecision(marketIndex, 100);
// transferDeposit(amount, marketIndex, fromSubAccountId, toSubAccountId)
await velocityClient.transferDeposit(amount, marketIndex, 0, 1);Method VelocityClient.transferDepositReference ↗
Method VelocityClient.transferDepositReference ↗| Parameter | Type | Required |
|---|---|---|
amount | anyAmount to transfer, in the spot market's own token precision. | Yes |
marketIndex | numberSpot market index of the balance to transfer. | Yes |
fromSubAccountId | numberSub-account id to debit. | Yes |
toSubAccountId | numberSub-account id to credit. | Yes |
txParams | TxParamsOptional compute-unit/priority-fee overrides for the transaction. | No |
| Returns |
|---|
Promise<string> |
Transfer a Perp Position Between Subaccounts
import { BASE_PRECISION, BN } from "@velocity-exchange/sdk";
// transferPerpPosition(fromSubAccountId, toSubAccountId, marketIndex, amount)
const amount = new BN(1).mul(BASE_PRECISION); // 1 base unit
await velocityClient.transferPerpPosition(0, 1, 0, amount);Method VelocityClient.transferPerpPositionReference ↗
Method VelocityClient.transferPerpPositionReference ↗| Parameter | Type | Required |
|---|---|---|
fromSubAccountId | numberSub-account id to debit the position from. | Yes |
toSubAccountId | numberSub-account id to credit the position to. | Yes |
marketIndex | numberPerp market index of the position to transfer. | Yes |
amount | anySigned base amount to transfer, in `BASE_PRECISION` (1e9). Must have the same sign
as `fromSubAccountId`'s existing position (i.e. it only reduces/closes that position, never
flips it) and a magnitude at most the position's size and a multiple of the market's step size;
pass `undefined` to transfer the entire position. | Yes |
txParams | TxParamsOptional compute-unit/priority-fee overrides for the transaction. | No |
| Returns |
|---|
Promise<string> |
Transfer a Deposit and a Borrow Between Subaccounts
transferPools moves a deposit position and a borrow position between two of your own subaccounts in a single instruction — useful for rebalancing collateral and debt together instead of issuing two separate transfers.
const depositAmount = velocityClient.convertToSpotPrecision(0, 100); // 100 USDC
const borrowAmount = velocityClient.convertToSpotPrecision(1, 1); // 1 SOL
// transferPools(depositFromMarketIndex, depositToMarketIndex, borrowFromMarketIndex,
// borrowToMarketIndex, depositAmount, borrowAmount, fromSubAccountId, toSubAccountId)
await velocityClient.transferPools(0, 0, 1, 1, depositAmount, borrowAmount, 0, 1);Method VelocityClient.transferPoolsReference ↗
Method VelocityClient.transferPoolsReference ↗| Parameter | Type | Required |
|---|---|---|
depositFromMarketIndex | numberSpot market to debit the deposit leg from. | Yes |
depositToMarketIndex | numberSpot market to credit the deposit leg to (same mint, different pool). | Yes |
borrowFromMarketIndex | numberSpot market to credit (repay) the borrow leg from. | Yes |
borrowToMarketIndex | numberSpot market to debit (re-open) the borrow leg on. | Yes |
depositAmount | anyDeposit amount to move, in the deposit market's token precision;
`undefined`/omitted moves the entire existing deposit token amount; `0` skips the deposit leg
entirely. | Yes |
borrowAmount | anyBorrow amount to move, in the borrow market's token precision; `undefined`
moves the entire existing borrow token amount; `0` skips the borrow leg entirely. | Yes |
fromSubAccountId | numberSub-account id to debit. | Yes |
toSubAccountId | numberSub-account id to credit. | Yes |
txParams | TxParamsOptional compute-unit/priority-fee overrides for the transaction. | No |
| Returns |
|---|
Promise<string> |
Transfer Collateral Into or Out of an Isolated Perp Position
transferIsolatedPerpPositionDeposit moves collateral between a subaccount’s shared cross-margin pool and one perp market’s dedicated isolated-position bucket — it does not move funds between subaccounts. Pass a positive amount to fund the isolated position from cross margin, or a negative amount to pull collateral back out of the isolated position into cross margin.
const perpMarketIndex = 0;
const amount = velocityClient.convertToSpotPrecision(0, 100); // deposit 100 USDC into the isolated position
// transferIsolatedPerpPositionDeposit(amount, perpMarketIndex, subAccountId?, txParams?, trySettle?, noBuffer?)
await velocityClient.transferIsolatedPerpPositionDeposit(amount, perpMarketIndex);
// Negative amount withdraws collateral from the isolated position back to cross margin
await velocityClient.transferIsolatedPerpPositionDeposit(amount.neg(), perpMarketIndex);Method VelocityClient.transferIsolatedPerpPositionDepositReference ↗
Method VelocityClient.transferIsolatedPerpPositionDepositReference ↗| Parameter | Type | Required |
|---|---|---|
amount | anySigned amount to move, in the quote spot market's token precision (e.g.
QUOTE_PRECISION (1e6) for USDC); positive = into the isolated position, negative = out of it. Pass
`MIN_I64` to move the entire isolated deposit back to general. | Yes |
perpMarketIndex | numberPerp market index of the isolated position. | Yes |
subAccountId | numberSub-account id owning the position; defaults to `this.activeSubAccountId`. | No |
txParams | TxParamsOptional compute-unit/priority-fee overrides for the transaction. | No |
trySettle | booleanIf `true`, always prepends the `TRY_SETTLE` instruction even if not otherwise
inferred as necessary. | No |
noBuffer | booleanIf `true`, sends `amount` unmodified; otherwise (default) adds a 0.5% buffer to
the requested amount to absorb price movement between build and execution. Has no effect when
`amount` is `MIN_I64`. | No |
| Returns |
|---|
Promise<string> |
Delegate Transfers
By default, a delegate (an address authorized via updateUserDelegate to trade on your behalf) cannot call transferDepositByDelegate — internal transfers by a delegate are opt-in. Before a delegate can move deposits between your subaccounts, the account authority must explicitly enable the allowDelegateTransfer flag on their UserStats account. The flag applies to every subaccount under that authority.
// Authority opts in, once, before any delegate can transfer deposits internally.
await velocityClient.updateUserAllowDelegateTransfer(true);Method VelocityClient.updateUserAllowDelegateTransferReference ↗
Method VelocityClient.updateUserAllowDelegateTransferReference ↗| Parameter | Type | Required |
|---|---|---|
allowDelegateTransfer | booleanNew value for the flag. | Yes |
| Returns |
|---|
Promise<string> |
Once opted in, a delegate can call transferDepositByDelegate with the same arguments as transferDeposit:
// velocityClient here is subscribed with the delegate wallet, not the authority.
const marketIndex = 0; // e.g. USDC
const amount = velocityClient.convertToSpotPrecision(marketIndex, 100);
// transferDepositByDelegate(amount, marketIndex, fromSubAccountId, toSubAccountId)
await velocityClient.transferDepositByDelegate(amount, marketIndex, 0, 1);Method VelocityClient.transferDepositByDelegateReference ↗
Method VelocityClient.transferDepositByDelegateReference ↗| Parameter | Type | Required |
|---|---|---|
amount | anyAmount to transfer, in the spot market's own token precision. | Yes |
marketIndex | numberSpot market index of the balance to transfer. | Yes |
fromSubAccountId | numberSub-account id to debit. | Yes |
toSubAccountId | numberSub-account id to credit. | Yes |
txParams | TxParamsOptional compute-unit/priority-fee overrides for the transaction. | No |
| Returns |
|---|
Promise<string> |
If allowDelegateTransfer has not been enabled, the on-chain instruction rejects the transfer regardless of whether the delegate is otherwise authorized to trade on the subaccounts involved.