Velocity ProtocolDevelopers
Migrate from Drift

Migrating from Drift

Velocity Protocol is a fork of Drift Protocol v2, taken at Drift SDK v2.163.0-beta.0. It is not an upgrade of Drift in place. It is an entirely new onchain program deployment with a new program ID, a reduced feature set, and its own renamed SDK. The Drift program is paused, and no onchain state carries over: user accounts must be re-initialized and balances start fresh on Velocity.

Because the program ID changed, every PDA address is different from Drift: even for the accounts whose seeds are byte-for-byte unchanged (user, user_stats, perp_market, spot_market, spot_market_vault, insurance_fund_vault). One trading seed was also renamed: the State PDA seed went from drift_state to velocity_state. Never reuse a Drift-derived address on Velocity.

At a glance

DriftVelocity
Program IDdRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UHvELoC1audYbSYVRXn1vPaV8Axoa9oU6BYmNGZZBDZ1P
npm package@drift-labs/sdk (2.163.0-beta.0)@velocity-exchange/sdk (0.20.0)
Client classDriftClientVelocityClient (no back-compat alias)
Anchor@coral-xyz/anchor@0.29.0@anchor-lang/core@1.0.1 (aliased as @coral-xyz/anchor)
IDL filedrift.jsonvelocity.json
Mainnet quote assetUSDCUSDT
Data API hostdata.api.drift.tradedata.velocity.exchange

This page covers the TypeScript SDK at @velocity-exchange/sdk 0.20.0. Rust (velocity-rs) and raw-ABI integrators need the full layout-and-ABI reference as well, which lives in the velocity-v1 monorepo. That repository is not public; ask the team for the document.

Quote asset is now USDT

This is the single most money-relevant change. On Drift, spot market 0 (the cross-margin quote and collateral asset) is USDC. On Velocity mainnet-beta it is USDT.

NetworkQuote mint
Drift mainnet (USDC)EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Velocity mainnet-beta (USDT)Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
Velocity devnet (dUSDT placeholder)GqmEqYsy8EyvofDpmtFxK8zhYrgWgNokAtYoduQdL7v6

Both are 6-decimal SPL tokens, so notional amounts look identical and nothing type-checks differently. A desk that funds accounts with USDC, as it did on Drift, is depositing the wrong token: deposits, withdrawals, ATA derivation, collateral, and settlement all reference the USDT mint.

Switch every quote-mint hardcode and associated token account to USDT on mainnet, and to dUSDT on devnet. Never assume QUOTE_MINT_ADDRESS == USDC. The reliable fix is to stop hardcoding the mint at all and read getConfig().QUOTE_MINT_ADDRESS; see Setup for the config accessor.

Removed features

Several Drift subsystems were dropped. Their SDK exports are gone (no back-compat), and their onchain error variants are preserved only as deprecated, code-stable stubs.

FeatureWhat changed
Spot DLOB tradingplace_spot_order, place_and_take_spot_order, place_and_make_spot_order, fill_spot_order are removed. Spot markets still exist (for collateral and borrow-lend) but placing orders on a spot book is not possible. Attempting it returns SpotDlobTradingDisabled (6350).
External spot fulfillmentSerum, Phoenix, and OpenBook fulfillment are gone. The serum/*, phoenix/*, openbook/* subscribers and fulfillment-config maps, and the SERUM_V3 / PHOENIX / OPENBOOK env config fields, are removed.
FuelThe math/fuel module and the FuelSeasonRecord / FuelSweepRecord event types are removed.
vAMM LP (BAMM) sharesLP provisioning on the vAMM is gone: PerpPosition.lp_shares and the LPRecord / LPAction types are removed.
Protected maker modeThe four protected-maker instructions, the ProtectedMakerModeConfig account type, and VelocityClient.updateUserProtectedMakerOrders are removed.
High leverage modeThe five HLM instructions and their config-account subscribers are removed. The onchain MarginMode enum and the User.marginMode field are gone. (The TS MarginMode class still exists in the SDK, reduced to DEFAULT only, so imports don't break.)
Prediction marketsinitialize_prediction_market is removed; ContractType.PREDICTION is now DEPRECATED_PREDICTION.
Legacy Pyth pull/pushThe legacy Pyth pull/push instructions are removed, along with oracles/pythPullClient and util/pythOracleUtils. Pyth Lazer is the supported Pyth path. The PythSolanaReceiver and WormholeCoreBridgeSolana root exports are also gone.
Switchboard oraclesoracles/switchboardClient and oracles/switchboardOnDemandClient are removed; the OracleSource Switchboard variants are renamed DEPRECATED_SWITCHBOARD / DEPRECATED_SWITCHBOARD_ON_DEMAND (discriminants preserved).
Gov-token stake fee discountsStaking a gov token for a fee discount is gone: updateUserGovTokenInsuranceStake, GOV_SPOT_MARKET_INDEX, and the delegate variant are removed. Perp fee tier is now based on 30-day volume, floored by an admin-set promo tier (see below).
IF rebalance / protocol-IF sharesProtocol-owned insurance-fund shares and IF rebalancing are removed (the admin IF-withdraw, protocol-IF-share transfer, IF-swap, and IF-rebalance-config instructions).
Legacy referrer-reward fee pathUserStats.fees.total_referrer_reward, UserStats.fees.current_epoch_referrer_reward, and UserStats.next_epoch_ts are deleted; FeeStructure.referrer_reward_epoch_upper_bound is now padding. The SDK's referrerInfo? param is dropped from placeAndMakePerpOrder, placeAndMakeSignedMsgPerpOrder, and fillPerpOrder.

New on Velocity

Velocity also adds subsystems Drift never had. In brief:

  • Velocity liquidity pool module: a liquidity-pool and vAMM-hedge component, configured per market through PerpMarketAccount.hedgeConfig.
  • Isolated perp positions: per-position isolated collateral. The instructions are feature-gated out of mainnet builds pending audit; the state layout is present in every build.
  • Builder codes: the change_approved_builder instruction, a RevenueShare escrow account, and ReferrerStatus.BuilderReferral = 4. See Builder Codes.
  • Tiered admin keys: the single State.admin is split into cold_admin, warm_admin, pause_admin, and a set of narrowly scoped hot keys. See Account Model.
  • Continuous funding dead zone: a per-market funding clamp threshold and ramp slope, fundingClampThreshold and fundingRampSlope.
  • Per-market funding-bias spread widening: an opt-in vAMM spread widen on the funding-paying side, off by default.
  • Fast-fill auctions: the DLOB server can force fast, marketable auctions. See the behavior changes below.
  • Protocol fee redesign: fees are re-routed through a three-way AMM, insurance fund, and protocol split rather than changing the taker rate itself.

Behavior changes to review

These are semantic changes a compiler cannot catch: a port that builds cleanly can still mispredict onchain behavior. What follows is the shortlist, ordered by impact for a market maker. Every item is enumerated in full, with the exact condition and the check to run, in Section 5 of the agent guide, which is the reference version of this list.

  • Quote asset is USDT on mainnet. See above. Funding an account with the wrong token is the highest-severity failure mode on this page.
  • Fast-fill auctions. At DLOB server API version 3 and above, every market is fast-fill: the auction starts inside the touch and lasts 2000ms of wall clock. Auctions become marketable almost immediately, so a maker quoting off stale prices gets run over. Derive the window from the live slot duration rather than hardcoding 5 slots, and use the generatedAt response field for staleness checks.
  • Trigger orders are priced at their post-trigger price. The Rust DLOB library used by fillers and keeper bots now rewrites a resting trigger order's book price to its computed post-trigger auction price, clamped to the limit price for TriggerLimit, instead of tagging it with the raw trigger price. Stop assuming a resting trigger order's book price equals its trigger price.
  • AMM JIT is dropped from match fills under a hard gate. With a pause, a drawdown, MM-oracle volatility, or an invalid oracle in force, a DLOB match fills DLOB-only and fills can be capped to the resting maker's size. Do not assume AMM JIT backstops a match.
  • MM-oracle native writes are throttled and clamped. update_mm_oracle_native silently skips a write, returning Ok with no error, on a non-positive price, a non-increasing sequence id, a non-advancing slot, or a source slot more than 800ms from the landing slot. An oversized price step is the exception: it is clamped to the 1% per-write cap and written, so a large move converges over several writes rather than freezing the oracle. Throttle crank writes to at least 800ms apart and expect no error signal when one is dropped.
  • The funding floor rose from 7.3% to 10.95% annualized. FUNDING_RATE_OFFSET_DENOMINATOR dropped from 5000 to 3333, making the always-applied floor and ceiling roughly 1.5x higher. The SDK mirror is in sync, so re-pull it and re-model funding carry on any perp inventory.
  • Fee costs changed for referred and previously staked accounts. The gov-token stake discount is gone; the perp fee tier now comes from 30-day volume, floored by the admin-set State.promo_fee_tier where 0 means no floor. Separately, getMarketFees now subtracts the referee discount, and calculateFeeForQuoteAmount became calculatePerpTakerFee, which rounds predicted fees up rather than down. Re-model taker fees with no stake benefit.
  • MarketStatus discriminants shifted. Four now-removed pause variants sat between Active and ReduceOnly on Drift, so ReduceOnly, Settlement, and Delisted were 6, 7, and 8. They are 2, 3, and 4 here. IDL-based decoding is fine; any custom raw-byte decoder silently misclassifies market state until it is rebuilt.
  • Bulk order margin is tighter. place_orders and place_scale_orders accumulate risk across the batch and check initial margin once per touched risk scope, instead of gating only the last order at maintenance margin. Batches that previously slipped a risk-increasing order past a weak gate now revert with InsufficientCollateral. Size batches against initial margin.
  • Deposits and transfers enforce per-market admission. Same-market transfer_deposit, its delegate variant, and direct deposit() now apply the full admission logic: active status, max_token_deposits, the reduce-only cap, and the per-market Deposit pause bit independently of the global pause. Calls that used to succeed against a capped, non-active, or reduce-only market now revert. Pre-check spot market status and caps.

Data API: Drift-only columns

The Data API's Trades/Market Trades tables drop the spotFulfillmentMethodFee column (external spot fulfillment is removed), and the Funding Rates table drops periodRevenue and baseAssetAmountWithUnsettledLp (vAMM LP shares are removed). One entire table has no Velocity equivalent:

LP (BAL), Drift-only, no Velocity equivalent. Drift's vAMM LP shares (PerpPosition.lpShares and the addLiquidity/settleLiquidity actions below) were removed entirely on Velocity. There is no per-user LP-share mechanism to emit these events. Liquidity provision against a market now happens through the separate Velocity liquidity pool module (a hedge-pool architecture configured per-market via PerpMarketAccount.hedgeConfig), which has its own accounting and does not map onto this table.

ColumnUnitDescription
actionaddLiquidity / settleLiquidity
nSharesintNumber of perpetual contract shares traded.
deltaBaseAssetAmountintChange in base asset position due to the trade.
deltaQuoteAssetAmountintChange in quote asset position due to the trade.
pnlintProfit or loss from the trade.

See the Data API glossary for the full current column reference.

SDK surface

The headline renames a TypeScript integrator hits first: there are no back-compat aliases, so these surface as build errors:

  • DriftClientVelocityClient
  • DRIFT_PROGRAM_IDVELOCITY_PROGRAM_ID
  • DriftEnvVelocityEnv
  • Account subscribers: webSocketDriftClientAccountSubscriber(V2)webSocketVelocityClientAccountSubscriber(V2), pollingDriftClientAccountSubscriberpollingVelocityClientAccountSubscriber, grpcDriftClientAccountSubscriber(V2)grpcVelocityClientAccountSubscriber(V2)
  • Config field USDC_MINT_ADDRESSQUOTE_MINT_ADDRESS
  • Order.oraclePriceOffset / OrderParams.oraclePriceOffset widened from number to BN: wrap raw numbers in new BN(...)
  • Removed root exports include PythSolanaReceiver and WormholeCoreBridgeSolana: importing either from the package root now breaks

Note also that the IDL account names are PascalCase (e.g. PerpMarket, SpotMarket, User). Pass those exact names to the account coder.

For the exhaustive symbol tables and a step-by-step procedure an AI coding agent can execute, see the AI Agent Migration Guide.

Scope & currency

This page reflects @velocity-exchange/sdk 0.20.0 and covers the TypeScript SDK. The canonical layout-and-ABI reference, which Rust (velocity-rs) and raw-ABI integrators need, is docs/DRIFT-TO-VELOCITY.md in the velocity-v1 monorepo. That repository is not public and will not be until the post-fork audit report is final, so ask the team for the document rather than looking for a clone URL.