UNPKG

@ox-fun/drift-sdk

Version:

SDK for Drift Protocol

655 lines (633 loc) 17.4 kB
import { Connection, Keypair, PublicKey } from '@solana/web3.js'; import { AMM, AssetTier, PerpPosition, BN, DriftClient, User, PerpMarketAccount, SpotMarketAccount, MarketStatus, ContractType, OracleSource, DevnetSpotMarkets, BASE_PRECISION, QUOTE_PRECISION, AMM_TO_QUOTE_PRECISION_RATIO, StateAccount, UserMapInterface, Wallet, OrderRecord, ZERO, ContractTier, SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, SPOT_MARKET_WEIGHT_PRECISION, PRICE_PRECISION, } from '../../src'; export const mockPerpPosition: PerpPosition = { baseAssetAmount: new BN(0), lastCumulativeFundingRate: new BN(0), marketIndex: 0, quoteAssetAmount: new BN(0), quoteBreakEvenAmount: new BN(0), quoteEntryAmount: new BN(0), openOrders: 0, openBids: new BN(0), openAsks: new BN(0), settledPnl: new BN(0), lpShares: new BN(0), remainderBaseAssetAmount: 0, lastBaseAssetAmountPerLp: new BN(0), lastQuoteAssetAmountPerLp: new BN(0), perLpBase: 0, }; export const mockAMM: AMM = { perLpBase: 0, /* these values create a bid/ask price of 12 */ baseAssetReserve: new BN(1).mul(BASE_PRECISION), quoteAssetReserve: new BN(12) .mul(QUOTE_PRECISION) .mul(AMM_TO_QUOTE_PRECISION_RATIO), sqrtK: new BN(1), pegMultiplier: new BN(1), maxSlippageRatio: 1_000_000, cumulativeFundingRate: new BN(0), lastFundingRate: new BN(0), lastFundingRateTs: new BN(0), lastMarkPriceTwap: new BN(0), lastMarkPriceTwap5Min: new BN(0), lastMarkPriceTwapTs: new BN(0), totalFeeEarnedPerLp: new BN(0), historicalOracleData: { lastOraclePrice: new BN(0), lastOracleConf: new BN(0), lastOracleDelay: new BN(0), lastOraclePriceTwap: new BN(0), lastOraclePriceTwap5Min: new BN(0), lastOraclePriceTwapTs: new BN(0), }, lastOracleReservePriceSpreadPct: new BN(0), lastOracleConfPct: new BN(0), oracle: PublicKey.default, oracleSource: OracleSource.PYTH, fundingPeriod: new BN(0), cumulativeFundingRateLong: new BN(0), cumulativeFundingRateShort: new BN(0), totalFeeMinusDistributions: new BN(0), totalFeeWithdrawn: new BN(0), totalFee: new BN(0), userLpShares: new BN(0), baseAssetAmountWithUnsettledLp: new BN(0), orderStepSize: new BN(0), orderTickSize: new BN(1), last24HAvgFundingRate: new BN(0), lastFundingRateShort: new BN(0), lastFundingRateLong: new BN(0), concentrationCoef: new BN(0), lastTradeTs: new BN(0), lastOracleNormalisedPrice: new BN(0), maxOpenInterest: new BN(0), totalLiquidationFee: new BN(0), maxFillReserveFraction: 0, baseSpread: 0, curveUpdateIntensity: 0, baseAssetAmountWithAmm: new BN(0), baseAssetAmountLong: new BN(0), baseAssetAmountShort: new BN(0), quoteAssetAmount: new BN(0), terminalQuoteAssetReserve: new BN(0), feePool: { scaledBalance: new BN(0), marketIndex: 0, }, totalExchangeFee: new BN(0), totalMmFee: new BN(0), netRevenueSinceLastFunding: new BN(0), lastUpdateSlot: new BN(0), lastOracleValid: true, lastBidPriceTwap: new BN(0), lastAskPriceTwap: new BN(0), longSpread: 0, shortSpread: 0, maxSpread: 0, ammJitIntensity: 0, maxBaseAssetReserve: new BN(0), minBaseAssetReserve: new BN(0), totalSocialLoss: new BN(0), baseAssetAmountPerLp: new BN(0), quoteAssetAmountPerLp: new BN(0), targetBaseAssetAmountPerLp: 0, quoteBreakEvenAmountLong: new BN(0), quoteBreakEvenAmountShort: new BN(0), quoteEntryAmountLong: new BN(0), quoteEntryAmountShort: new BN(0), markStd: new BN(0), oracleStd: new BN(0), longIntensityCount: 0, longIntensityVolume: new BN(0), shortIntensityCount: 0, shortIntensityVolume: new BN(0), volume24H: new BN(0), minOrderSize: new BN(0), maxPositionSize: new BN(0), bidBaseAssetReserve: new BN(0), bidQuoteAssetReserve: new BN(0), askBaseAssetReserve: new BN(0), askQuoteAssetReserve: new BN(0), }; export const mockPerpMarkets: Array<PerpMarketAccount> = [ { status: MarketStatus.INITIALIZED, name: [], contractType: ContractType.PERPETUAL, contractTier: ContractTier.A, expiryTs: new BN(0), expiryPrice: new BN(0), marketIndex: 0, pubkey: PublicKey.default, amm: mockAMM, numberOfUsersWithBase: 0, numberOfUsers: 0, marginRatioInitial: 2000, marginRatioMaintenance: 1000, nextFillRecordId: new BN(0), pnlPool: { scaledBalance: new BN(0), marketIndex: 0, }, ifLiquidationFee: 0, liquidatorFee: 0, imfFactor: 0, nextFundingRateRecordId: new BN(0), nextCurveRecordId: new BN(0), unrealizedPnlImfFactor: 0, unrealizedPnlMaxImbalance: ZERO, unrealizedPnlInitialAssetWeight: 0, unrealizedPnlMaintenanceAssetWeight: 0, insuranceClaim: { revenueWithdrawSinceLastSettle: new BN(0), maxRevenueWithdrawPerPeriod: new BN(0), lastRevenueWithdrawTs: new BN(0), quoteSettledInsurance: new BN(0), quoteMaxInsurance: new BN(0), }, quoteSpotMarketIndex: 0, feeAdjustment: 0, }, { status: MarketStatus.INITIALIZED, contractTier: ContractTier.A, nextFundingRateRecordId: new BN(0), nextCurveRecordId: new BN(0), name: [], contractType: ContractType.PERPETUAL, expiryTs: new BN(0), expiryPrice: new BN(0), marketIndex: 1, pubkey: PublicKey.default, amm: mockAMM, numberOfUsersWithBase: 0, numberOfUsers: 0, marginRatioInitial: 0, marginRatioMaintenance: 0, nextFillRecordId: new BN(0), pnlPool: { scaledBalance: new BN(0), marketIndex: 0, }, ifLiquidationFee: 0, liquidatorFee: 0, imfFactor: 0, unrealizedPnlImfFactor: 0, unrealizedPnlMaxImbalance: ZERO, unrealizedPnlInitialAssetWeight: 0, unrealizedPnlMaintenanceAssetWeight: 0, insuranceClaim: { revenueWithdrawSinceLastSettle: new BN(0), maxRevenueWithdrawPerPeriod: new BN(0), lastRevenueWithdrawTs: new BN(0), quoteSettledInsurance: new BN(0), quoteMaxInsurance: new BN(0), }, quoteSpotMarketIndex: 0, feeAdjustment: 0, }, { status: MarketStatus.INITIALIZED, contractTier: ContractTier.A, nextFundingRateRecordId: new BN(0), nextCurveRecordId: new BN(0), name: [], contractType: ContractType.PERPETUAL, expiryTs: new BN(0), expiryPrice: new BN(0), marketIndex: 2, pubkey: PublicKey.default, amm: mockAMM, numberOfUsersWithBase: 0, numberOfUsers: 0, marginRatioInitial: 0, marginRatioMaintenance: 0, nextFillRecordId: new BN(0), pnlPool: { scaledBalance: new BN(0), marketIndex: 0, }, ifLiquidationFee: 0, liquidatorFee: 0, imfFactor: 0, unrealizedPnlImfFactor: 0, unrealizedPnlMaxImbalance: ZERO, unrealizedPnlInitialAssetWeight: 0, unrealizedPnlMaintenanceAssetWeight: 0, insuranceClaim: { revenueWithdrawSinceLastSettle: new BN(0), maxRevenueWithdrawPerPeriod: new BN(0), lastRevenueWithdrawTs: new BN(0), quoteSettledInsurance: new BN(0), quoteMaxInsurance: new BN(0), }, quoteSpotMarketIndex: 0, feeAdjustment: 0, }, ]; export const mockSpotMarkets: Array<SpotMarketAccount> = [ { status: MarketStatus.ACTIVE, assetTier: AssetTier.COLLATERAL, name: [], maxTokenDeposits: new BN(1000000 * QUOTE_PRECISION.toNumber()), marketIndex: 0, pubkey: PublicKey.default, mint: DevnetSpotMarkets[0].mint, vault: PublicKey.default, minOrderSize: ZERO, maxPositionSize: ZERO, revenuePool: { scaledBalance: new BN(0), marketIndex: 0, }, insuranceFund: { vault: PublicKey.default, totalShares: new BN(0), userShares: new BN(0), sharesBase: new BN(0), unstakingPeriod: new BN(0), lastRevenueSettleTs: new BN(0), revenueSettlePeriod: new BN(0), totalFactor: 0, userFactor: 0, }, ifLiquidationFee: 0, liquidatorFee: 0, decimals: 6, optimalUtilization: 0, optimalBorrowRate: 0, maxBorrowRate: 0, cumulativeDepositInterest: SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, cumulativeBorrowInterest: SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, totalSocialLoss: new BN(0), totalQuoteSocialLoss: new BN(0), depositBalance: new BN(0), borrowBalance: new BN(0), lastInterestTs: new BN(0), lastTwapTs: new BN(0), oracle: PublicKey.default, initialAssetWeight: SPOT_MARKET_WEIGHT_PRECISION.toNumber(), maintenanceAssetWeight: SPOT_MARKET_WEIGHT_PRECISION.toNumber(), initialLiabilityWeight: SPOT_MARKET_WEIGHT_PRECISION.toNumber(), maintenanceLiabilityWeight: SPOT_MARKET_WEIGHT_PRECISION.toNumber(), scaleInitialAssetWeightStart: new BN(0), imfFactor: 0, withdrawGuardThreshold: new BN(0), depositTokenTwap: new BN(0), borrowTokenTwap: new BN(0), utilizationTwap: new BN(0), orderStepSize: new BN(0), orderTickSize: new BN(0), nextFillRecordId: new BN(0), nextDepositRecordId: new BN(0), ordersEnabled: true, spotFeePool: { scaledBalance: new BN(0), marketIndex: 0, }, totalSpotFee: new BN(0), totalSwapFee: new BN(0), flashLoanAmount: new BN(0), flashLoanInitialTokenAmount: new BN(0), oracleSource: OracleSource.PYTH, historicalOracleData: { lastOraclePrice: PRICE_PRECISION, lastOracleConf: new BN(0), lastOracleDelay: new BN(0), lastOraclePriceTwap: PRICE_PRECISION, lastOraclePriceTwap5Min: PRICE_PRECISION, lastOraclePriceTwapTs: new BN(0), }, historicalIndexData: { lastIndexBidPrice: PRICE_PRECISION, lastIndexAskPrice: PRICE_PRECISION, lastIndexPriceTwap: PRICE_PRECISION, lastIndexPriceTwap5Min: PRICE_PRECISION, lastIndexPriceTwapTs: new BN(0), }, }, { status: MarketStatus.ACTIVE, assetTier: AssetTier.CROSS, name: [], maxTokenDeposits: new BN(100), marketIndex: 1, pubkey: PublicKey.default, mint: DevnetSpotMarkets[1].mint, vault: PublicKey.default, revenuePool: { scaledBalance: new BN(0), marketIndex: 0, }, minOrderSize: ZERO, maxPositionSize: ZERO, insuranceFund: { vault: PublicKey.default, totalShares: new BN(0), userShares: new BN(0), sharesBase: new BN(0), unstakingPeriod: new BN(0), lastRevenueSettleTs: new BN(0), revenueSettlePeriod: new BN(0), totalFactor: 0, userFactor: 0, }, ifLiquidationFee: 0, liquidatorFee: 0, decimals: 9, optimalUtilization: 0, optimalBorrowRate: 0, maxBorrowRate: 0, cumulativeDepositInterest: SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, cumulativeBorrowInterest: SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, totalSocialLoss: new BN(0), totalQuoteSocialLoss: new BN(0), depositBalance: new BN(0), borrowBalance: new BN(0), lastInterestTs: new BN(0), lastTwapTs: new BN(0), oracle: PublicKey.default, initialAssetWeight: 0, maintenanceAssetWeight: 0, initialLiabilityWeight: 0, maintenanceLiabilityWeight: 0, scaleInitialAssetWeightStart: new BN(0), imfFactor: 0, withdrawGuardThreshold: new BN(0), depositTokenTwap: new BN(0), borrowTokenTwap: new BN(0), utilizationTwap: new BN(0), orderStepSize: new BN(0), orderTickSize: new BN(0), nextFillRecordId: new BN(0), nextDepositRecordId: new BN(0), ordersEnabled: true, spotFeePool: { scaledBalance: new BN(0), marketIndex: 0, }, totalSpotFee: new BN(0), totalSwapFee: new BN(0), flashLoanAmount: new BN(0), flashLoanInitialTokenAmount: new BN(0), oracleSource: OracleSource.PYTH, historicalOracleData: { lastOraclePrice: new BN(0), lastOracleConf: new BN(0), lastOracleDelay: new BN(0), lastOraclePriceTwap: new BN(0), lastOraclePriceTwap5Min: new BN(0), lastOraclePriceTwapTs: new BN(0), }, historicalIndexData: { lastIndexBidPrice: new BN(0), lastIndexAskPrice: new BN(0), lastIndexPriceTwap: new BN(0), lastIndexPriceTwap5Min: new BN(0), lastIndexPriceTwapTs: new BN(0), }, }, { status: MarketStatus.ACTIVE, assetTier: AssetTier.PROTECTED, name: [], maxTokenDeposits: new BN(100), marketIndex: 2, pubkey: PublicKey.default, mint: DevnetSpotMarkets[2].mint, vault: PublicKey.default, revenuePool: { scaledBalance: new BN(0), marketIndex: 0, }, minOrderSize: ZERO, maxPositionSize: ZERO, insuranceFund: { vault: PublicKey.default, totalShares: new BN(0), userShares: new BN(0), sharesBase: new BN(0), unstakingPeriod: new BN(0), lastRevenueSettleTs: new BN(0), revenueSettlePeriod: new BN(0), totalFactor: 0, userFactor: 0, }, ifLiquidationFee: 0, liquidatorFee: 0, decimals: 6, optimalUtilization: 0, optimalBorrowRate: 0, maxBorrowRate: 0, cumulativeDepositInterest: SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, cumulativeBorrowInterest: SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION, totalSocialLoss: new BN(0), totalQuoteSocialLoss: new BN(0), depositBalance: new BN(0), borrowBalance: new BN(0), lastInterestTs: new BN(0), lastTwapTs: new BN(0), oracle: PublicKey.default, initialAssetWeight: 0, maintenanceAssetWeight: 0, initialLiabilityWeight: 0, maintenanceLiabilityWeight: 0, scaleInitialAssetWeightStart: new BN(0), imfFactor: 0, withdrawGuardThreshold: new BN(0), depositTokenTwap: new BN(0), borrowTokenTwap: new BN(0), utilizationTwap: new BN(0), orderStepSize: new BN(0), orderTickSize: new BN(0), nextFillRecordId: new BN(0), nextDepositRecordId: new BN(0), ordersEnabled: true, spotFeePool: { scaledBalance: new BN(0), marketIndex: 0, }, totalSpotFee: new BN(0), totalSwapFee: new BN(0), flashLoanAmount: new BN(0), flashLoanInitialTokenAmount: new BN(0), oracleSource: OracleSource.PYTH, historicalOracleData: { lastOraclePrice: new BN(0), lastOracleConf: new BN(0), lastOracleDelay: new BN(0), lastOraclePriceTwap: new BN(0), lastOraclePriceTwap5Min: new BN(0), lastOraclePriceTwapTs: new BN(0), }, historicalIndexData: { lastIndexBidPrice: new BN(0), lastIndexAskPrice: new BN(0), lastIndexPriceTwap: new BN(0), lastIndexPriceTwap5Min: new BN(0), lastIndexPriceTwapTs: new BN(0), }, }, ]; export const mockStateAccount: StateAccount = { admin: PublicKey.default, defaultMarketOrderTimeInForce: 0, defaultSpotAuctionDuration: 0, discountMint: PublicKey.default, exchangeStatus: 0, liquidationMarginBufferRatio: 0, lpCooldownTime: new BN(0), minPerpAuctionDuration: 0, numberOfMarkets: 0, numberOfSpotMarkets: 0, numberOfSubAccounts: new BN(0), numberOfAuthorities: new BN(0), initialPctToLiquidate: 0, liquidationDuration: 0, oracleGuardRails: { priceDivergence: { markOraclePercentDivergence: new BN(0), oracleTwap5MinPercentDivergence: new BN(0), }, validity: { slotsBeforeStaleForAmm: new BN(0), slotsBeforeStaleForMargin: new BN(0), confidenceIntervalMaxSize: new BN(0), tooVolatileRatio: new BN(0), }, }, perpFeeStructure: { feeTiers: [ { feeNumerator: 0, feeDenominator: 0, makerRebateNumerator: 0, makerRebateDenominator: 1, referrerRewardNumerator: 0, referrerRewardDenominator: 0, refereeFeeNumerator: 0, refereeFeeDenominator: 0, }, ], fillerRewardStructure: { rewardNumerator: new BN(0), rewardDenominator: new BN(0), timeBasedRewardLowerBound: new BN(0), }, flatFillerFee: new BN(0), referrerRewardEpochUpperBound: new BN(0), }, settlementDuration: 0, signer: PublicKey.default, signerNonce: 0, spotFeeStructure: { feeTiers: [ { feeNumerator: 0, feeDenominator: 0, makerRebateNumerator: 0, makerRebateDenominator: 1, referrerRewardNumerator: 0, referrerRewardDenominator: 0, refereeFeeNumerator: 0, refereeFeeDenominator: 0, }, ], fillerRewardStructure: { rewardNumerator: new BN(0), rewardDenominator: new BN(0), timeBasedRewardLowerBound: new BN(0), }, flatFillerFee: new BN(0), referrerRewardEpochUpperBound: new BN(0), }, srmVault: PublicKey.default, whitelistMint: PublicKey.default, maxNumberOfSubAccounts: 0, maxInitializeUserFee: 0, }; export class MockUserMap implements UserMapInterface { private userMap = new Map<string, User>(); private userAccountToAuthority = new Map<string, string>(); private driftClient: DriftClient; constructor() { this.userMap = new Map(); this.userAccountToAuthority = new Map(); this.driftClient = new DriftClient({ connection: new Connection('http://localhost:8899'), wallet: new Wallet(new Keypair()), programID: PublicKey.default, }); } public async subscribe(): Promise<void> {} public async unsubscribe(): Promise<void> {} public async addPubkey(userAccountPublicKey: PublicKey): Promise<void> { const user = new User({ driftClient: this.driftClient, userAccountPublicKey: userAccountPublicKey, }); this.userMap.set(userAccountPublicKey.toBase58(), user); } // mock function public addUserAccountAuthority( userAccountPublicKey: PublicKey, authorityPublicKey: PublicKey ): void { if (!this.userMap.has(userAccountPublicKey.toBase58())) { this.addPubkey(userAccountPublicKey); } this.userAccountToAuthority.set( userAccountPublicKey.toBase58(), authorityPublicKey.toBase58() ); } public has(key: string): boolean { return this.userMap.has(key); } public get(_key: string): User | undefined { return undefined; } public async mustGet(_key: string): Promise<User> { return new User({ driftClient: this.driftClient, userAccountPublicKey: PublicKey.default, }); } public getUserAuthority(key: string): PublicKey | undefined { return new PublicKey( this.userAccountToAuthority.get(key) || PublicKey.default.toBase58() ); } public async updateWithOrderRecord(_record: OrderRecord): Promise<void> {} public values(): IterableIterator<User> { return this.userMap.values(); } }