@velocity-exchange/sdk 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/adminClient.d.ts +24 -4
- package/lib/browser/adminClient.js +62 -12
- package/lib/browser/blockhashSubscriber/BlockhashSubscriber.d.ts +19 -15
- package/lib/browser/blockhashSubscriber/BlockhashSubscriber.js +31 -22
- package/lib/browser/constants/numericConstants.d.ts +2 -0
- package/lib/browser/constants/numericConstants.js +3 -1
- package/lib/browser/core/VelocityCore.d.ts +2 -0
- package/lib/browser/core/VelocityCore.js +1 -0
- package/lib/browser/core/instructions/trigger.d.ts +4 -0
- package/lib/browser/core/instructions/trigger.js +4 -0
- package/lib/browser/idl/velocity.d.ts +223 -33
- package/lib/browser/idl/velocity.json +224 -34
- package/lib/browser/math/amm.d.ts +8 -8
- package/lib/browser/math/funding.d.ts +2 -2
- package/lib/browser/math/liquidation.d.ts +37 -2
- package/lib/browser/math/liquidation.js +44 -3
- package/lib/browser/math/market.d.ts +5 -4
- package/lib/browser/math/market.js +21 -14
- package/lib/browser/math/oracles.d.ts +3 -3
- package/lib/browser/math/orders.d.ts +1 -1
- package/lib/browser/math/spotBalance.d.ts +13 -0
- package/lib/browser/math/spotBalance.js +43 -2
- package/lib/browser/testClient.js +12 -1
- package/lib/browser/tx/txHandler.d.ts +7 -1
- package/lib/browser/tx/txHandler.js +7 -3
- package/lib/browser/types.d.ts +9 -0
- package/lib/browser/user.d.ts +2 -2
- package/lib/browser/userMap/userMap.d.ts +1 -0
- package/lib/browser/userMap/userMap.js +3 -7
- package/lib/browser/velocityClient.d.ts +32 -20
- package/lib/browser/velocityClient.js +48 -23
- package/lib/node/adminClient.d.ts +24 -4
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +62 -12
- package/lib/node/blockhashSubscriber/BlockhashSubscriber.d.ts +19 -15
- package/lib/node/blockhashSubscriber/BlockhashSubscriber.d.ts.map +1 -1
- package/lib/node/blockhashSubscriber/BlockhashSubscriber.js +31 -22
- package/lib/node/constants/numericConstants.d.ts +2 -0
- package/lib/node/constants/numericConstants.d.ts.map +1 -1
- package/lib/node/constants/numericConstants.js +3 -1
- package/lib/node/core/VelocityCore.d.ts +2 -0
- package/lib/node/core/VelocityCore.d.ts.map +1 -1
- package/lib/node/core/VelocityCore.js +1 -0
- package/lib/node/core/instructions/trigger.d.ts +4 -0
- package/lib/node/core/instructions/trigger.d.ts.map +1 -1
- package/lib/node/core/instructions/trigger.js +4 -0
- package/lib/node/idl/velocity.d.ts +223 -33
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +224 -34
- package/lib/node/math/amm.d.ts +8 -8
- package/lib/node/math/amm.d.ts.map +1 -1
- package/lib/node/math/funding.d.ts +2 -2
- package/lib/node/math/funding.d.ts.map +1 -1
- package/lib/node/math/liquidation.d.ts +37 -2
- package/lib/node/math/liquidation.d.ts.map +1 -1
- package/lib/node/math/liquidation.js +44 -3
- package/lib/node/math/market.d.ts +5 -4
- package/lib/node/math/market.d.ts.map +1 -1
- package/lib/node/math/market.js +21 -14
- package/lib/node/math/oracles.d.ts +3 -3
- package/lib/node/math/oracles.d.ts.map +1 -1
- package/lib/node/math/orders.d.ts +1 -1
- package/lib/node/math/orders.d.ts.map +1 -1
- package/lib/node/math/spotBalance.d.ts +13 -0
- package/lib/node/math/spotBalance.d.ts.map +1 -1
- package/lib/node/math/spotBalance.js +43 -2
- package/lib/node/testClient.d.ts.map +1 -1
- package/lib/node/testClient.js +12 -1
- package/lib/node/tx/txHandler.d.ts +7 -1
- package/lib/node/tx/txHandler.d.ts.map +1 -1
- package/lib/node/tx/txHandler.js +7 -3
- package/lib/node/types.d.ts +9 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +2 -2
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/userMap/userMap.d.ts +1 -0
- package/lib/node/userMap/userMap.d.ts.map +1 -1
- package/lib/node/userMap/userMap.js +3 -7
- package/lib/node/velocityClient.d.ts +32 -20
- package/lib/node/velocityClient.d.ts.map +1 -1
- package/lib/node/velocityClient.js +48 -23
- package/package.json +1 -1
|
@@ -244,10 +244,11 @@ exports.calculateNetUserPnlImbalance = calculateNetUserPnlImbalance;
|
|
|
244
244
|
/**
|
|
245
245
|
* Calculates the price used to evaluate trigger (stop/take-profit) orders for a perp market,
|
|
246
246
|
* mirroring the Rust `get_trigger_price`. When `useMedianPrice` is true, the trigger price is the
|
|
247
|
-
* median of three candidates — the last fill price (or oracle price if there's been no fill
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
* oracle price (tier A/B: 20bps,
|
|
247
|
+
* median of three candidates — the last fill price (or oracle price if there's been no fill or the
|
|
248
|
+
* last fill is older than `TRIGGER_PRICE_LAST_FILL_MAX_AGE`), the oracle price adjusted by the
|
|
249
|
+
* implied funding basis, and the oracle price adjusted by the 5min mark/oracle TWAP basis — then
|
|
250
|
+
* clamped to within a contract-tier-dependent band around the raw oracle price (tier A/B: 20bps,
|
|
251
|
+
* tier C: 100bps, others: 250bps) via `clampTriggerPrice`. This
|
|
251
252
|
* resists a single manipulated print (last fill or a momentary oracle/mark divergence) from
|
|
252
253
|
* triggering orders it shouldn't. When `useMedianPrice` is false, the raw oracle price is used
|
|
253
254
|
* directly with no smoothing.
|
|
@@ -265,17 +266,23 @@ function getTriggerPrice(market, oraclePrice, now, useMedianPrice) {
|
|
|
265
266
|
if (!useMedianPrice) {
|
|
266
267
|
return oraclePrice.abs();
|
|
267
268
|
}
|
|
269
|
+
// Leg A: last trade price, only while fresh. `lastTradeTs` is stamped by
|
|
270
|
+
// the same fill path that writes `lastFillPrice`.
|
|
268
271
|
const lastFillPrice = market.lastFillPrice;
|
|
269
|
-
|
|
272
|
+
const lastFillIsFresh = now
|
|
273
|
+
.sub(market.marketStats.lastTradeTs)
|
|
274
|
+
.lte(numericConstants_1.TRIGGER_PRICE_LAST_FILL_MAX_AGE);
|
|
275
|
+
// Leg C: oracle + (mark_twap_5min - oracle_twap_5min)
|
|
270
276
|
const markPrice5minTwap = market.marketStats.lastMarkPriceTwap5Min;
|
|
271
277
|
const lastOraclePriceTwap5min = market.marketStats.historicalOracleData.lastOraclePriceTwap5Min;
|
|
272
278
|
const basis5min = markPrice5minTwap.sub(lastOraclePriceTwap5min);
|
|
273
279
|
const oraclePlusBasis5min = oraclePrice.add(basis5min);
|
|
274
|
-
//
|
|
280
|
+
// Leg B: oracle + decayed funding basis
|
|
275
281
|
const lastFundingBasis = getLastFundingBasis(market, oraclePrice, now);
|
|
276
282
|
const oraclePlusFundingBasis = oraclePrice.add(lastFundingBasis);
|
|
283
|
+
// No fill yet or last fill is stale: oracle price stands in for Leg A
|
|
277
284
|
const prices = [
|
|
278
|
-
lastFillPrice.gt(numericConstants_1.ZERO) ? lastFillPrice : oraclePrice,
|
|
285
|
+
lastFillPrice.gt(numericConstants_1.ZERO) && lastFillIsFresh ? lastFillPrice : oraclePrice,
|
|
279
286
|
oraclePlusFundingBasis,
|
|
280
287
|
oraclePlusBasis5min,
|
|
281
288
|
].sort((a, b) => a.cmp(b));
|
|
@@ -294,11 +301,11 @@ function getLastFundingBasis(market, oraclePrice, now) {
|
|
|
294
301
|
.div(market.marketStats.lastFundingOracleTwap)
|
|
295
302
|
.muln(24);
|
|
296
303
|
const lastFundingRatePreAdj = lastFundingRate.sub(numericConstants_1.FUNDING_RATE_OFFSET_PERCENTAGE);
|
|
297
|
-
const
|
|
304
|
+
const timeSinceFundingUpdate = anchor_1.BN.min(anchor_1.BN.max(now.sub(market.lastFundingRateTs), numericConstants_1.ZERO), market.marketStats.fundingPeriod);
|
|
298
305
|
const lastFundingBasis = oraclePrice
|
|
299
306
|
.mul(lastFundingRatePreAdj)
|
|
300
307
|
.div(numericConstants_1.PERCENTAGE_PRECISION)
|
|
301
|
-
.mul(market.marketStats.fundingPeriod.sub(
|
|
308
|
+
.mul(market.marketStats.fundingPeriod.sub(timeSinceFundingUpdate))
|
|
302
309
|
.div(market.marketStats.fundingPeriod)
|
|
303
310
|
.div(new anchor_1.BN(1000)); // FUNDING_RATE_BUFFER
|
|
304
311
|
return lastFundingBasis;
|
|
@@ -312,17 +319,17 @@ function getLastFundingBasis(market, oraclePrice, now) {
|
|
|
312
319
|
* Implements the same logic as the Rust clamp_trigger_price function
|
|
313
320
|
*/
|
|
314
321
|
function clampTriggerPrice(market, oraclePrice, medianPrice) {
|
|
315
|
-
let
|
|
322
|
+
let clampDivisor;
|
|
316
323
|
const tier = market.contractTier;
|
|
317
324
|
if ((0, types_1.isVariant)(tier, 'a') || (0, types_1.isVariant)(tier, 'b')) {
|
|
318
|
-
|
|
325
|
+
clampDivisor = new anchor_1.BN(500); // oracle / 500 = 20 bps
|
|
319
326
|
}
|
|
320
327
|
else if ((0, types_1.isVariant)(tier, 'c')) {
|
|
321
|
-
|
|
328
|
+
clampDivisor = new anchor_1.BN(100); // oracle / 100 = 100 bps
|
|
322
329
|
}
|
|
323
330
|
else {
|
|
324
|
-
|
|
331
|
+
clampDivisor = new anchor_1.BN(40); // oracle / 40 = 250 bps
|
|
325
332
|
}
|
|
326
|
-
const maxOracleDiff = oraclePrice.div(
|
|
333
|
+
const maxOracleDiff = oraclePrice.div(clampDivisor);
|
|
327
334
|
return anchor_1.BN.min(anchor_1.BN.max(medianPrice, oraclePrice.sub(maxOracleDiff)), oraclePrice.add(maxOracleDiff));
|
|
328
335
|
}
|
|
@@ -88,7 +88,7 @@ export declare function isMarkOracleTooDivergent(priceSpreadPct: BN, oracleGuard
|
|
|
88
88
|
* @param period TWAP window length in seconds — pass `FIVE_MINUTE` for the 5-minute TWAP, otherwise the funding period is assumed.
|
|
89
89
|
* @returns Live-projected oracle TWAP, PRICE_PRECISION (1e6).
|
|
90
90
|
*/
|
|
91
|
-
export declare function calculateLiveOracleTwap(histOracleData: HistoricalOracleData, oraclePriceData: OraclePriceData, now: BN, period: BN): BN;
|
|
91
|
+
export declare function calculateLiveOracleTwap(histOracleData: HistoricalOracleData, oraclePriceData: Pick<OraclePriceData, 'price'>, now: BN, period: BN): BN;
|
|
92
92
|
/**
|
|
93
93
|
* Live-projected oracle price standard deviation, combining the live oracle price's
|
|
94
94
|
* deviation from the freshly-projected 1hr and 5min TWAPs with the decayed stored
|
|
@@ -98,7 +98,7 @@ export declare function calculateLiveOracleTwap(histOracleData: HistoricalOracle
|
|
|
98
98
|
* @param now Current unix timestamp (seconds).
|
|
99
99
|
* @returns Live oracle price standard deviation, PRICE_PRECISION (1e6).
|
|
100
100
|
*/
|
|
101
|
-
export declare function calculateLiveOracleStd(marketStats: MarketStats, oraclePriceData: OraclePriceData, now: BN): BN;
|
|
101
|
+
export declare function calculateLiveOracleStd(marketStats: MarketStats, oraclePriceData: Pick<OraclePriceData, 'price'>, now: BN): BN;
|
|
102
102
|
/**
|
|
103
103
|
* Live-projected oracle confidence interval as a fraction of `reservePrice`, floored by a
|
|
104
104
|
* decaying lower bound derived from the market's last stored confidence (so confidence
|
|
@@ -111,7 +111,7 @@ export declare function calculateLiveOracleStd(marketStats: MarketStats, oracleP
|
|
|
111
111
|
* @param now Current unix timestamp (seconds).
|
|
112
112
|
* @returns Oracle confidence as a fraction of price, BID_ASK_SPREAD_PRECISION (1e6).
|
|
113
113
|
*/
|
|
114
|
-
export declare function getNewOracleConfPct(marketStats: MarketStats, oraclePriceData: OraclePriceData, reservePrice: BN, now: BN): BN;
|
|
114
|
+
export declare function getNewOracleConfPct(marketStats: MarketStats, oraclePriceData: Pick<OraclePriceData, 'confidence'>, reservePrice: BN, now: BN): BN;
|
|
115
115
|
/**
|
|
116
116
|
* Returns the scale factor to convert a price quoted under `firstOracleSource` into the
|
|
117
117
|
* equivalent price under `secondOracleSource`, for the Pyth Lazer "scaled" variants
|
|
@@ -89,7 +89,7 @@ export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, ma
|
|
|
89
89
|
* @param mmOraclePriceData Current MM oracle price data.
|
|
90
90
|
* @returns Fillable base asset amount up to the limit price, BASE_PRECISION (1e9).
|
|
91
91
|
*/
|
|
92
|
-
export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, amm: AMM, marketStats: MarketStats, orderStepSize: BN, orderTickSize: BN, limitPrice: BN, mmOraclePriceData: MMOraclePriceData): BN;
|
|
92
|
+
export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, amm: AMM, marketStats: MarketStats, orderStepSize: BN, orderTickSize: BN, limitPrice: BN, mmOraclePriceData: Pick<MMOraclePriceData, 'price' | 'confidence'>): BN;
|
|
93
93
|
/**
|
|
94
94
|
* True if `order.maxTs` has passed as of `ts`. Never true for trigger orders, non-`open`
|
|
95
95
|
* orders, or orders with no expiry (`maxTs == 0`).
|
|
@@ -241,6 +241,19 @@ export declare function calculateWithdrawLimit(spotMarket: SpotMarketAccount, no
|
|
|
241
241
|
currentDepositAmount: BN;
|
|
242
242
|
currentBorrowAmount: BN;
|
|
243
243
|
};
|
|
244
|
+
/**
|
|
245
|
+
* Mirror of the program's `calculate_max_deposit_token_amount`. Returns the max
|
|
246
|
+
* resulting deposit token amount permitted by the daily deposit cap: growth up
|
|
247
|
+
* to `maxDepositBpsPerDay` above the 24h deposit TWAP, but never below the
|
|
248
|
+
* deposit guard threshold. Returns null when the cap is disabled (pct == 0).
|
|
249
|
+
*/
|
|
250
|
+
export declare function calculateMaxDepositTokenAmount(depositTokenTwap: BN, depositGuardThreshold: BN, maxDepositBpsPerDay: number): BN | null;
|
|
251
|
+
/**
|
|
252
|
+
* Mirror of the program's `check_deposit_limits`. Returns true if the market's
|
|
253
|
+
* current deposit level is within the daily deposit cap (always true when the
|
|
254
|
+
* cap is disabled).
|
|
255
|
+
*/
|
|
256
|
+
export declare function checkDepositLimits(spotMarket: SpotMarketAccount): boolean;
|
|
244
257
|
/**
|
|
245
258
|
* Calculates the margin-weighted value of a spot deposit, mirroring the asset-side of the
|
|
246
259
|
* program's collateral valuation (`get_strict_token_value` + `get_asset_weight`). Uses the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSpotLiabilityValue = exports.getSpotAssetValue = exports.calculateWithdrawLimit = exports.calculateTokenUtilizationLimits = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateScaledInitialAssetWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
|
|
3
|
+
exports.getSpotLiabilityValue = exports.getSpotAssetValue = exports.checkDepositLimits = exports.calculateMaxDepositTokenAmount = exports.calculateWithdrawLimit = exports.calculateTokenUtilizationLimits = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateScaledInitialAssetWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const anchor_1 = require("../isomorphic/anchor");
|
|
6
6
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
@@ -571,7 +571,14 @@ function calculateWithdrawLimit(spotMarket, now) {
|
|
|
571
571
|
else {
|
|
572
572
|
maxBorrowTokensTwap = anchor_1.BN.max(spotMarket.withdrawGuardThreshold, anchor_1.BN.min(anchor_1.BN.max(lesserDepositAmount.div(new anchor_1.BN(2)), borrowTokenTwapLive.add(lesserDepositAmount.div(new anchor_1.BN(3)))), lesserDepositAmount.sub(lesserDepositAmount.div(new anchor_1.BN(20))))); // isolated pools between 50-95% utilization with friction on twap in 33% increments
|
|
573
573
|
}
|
|
574
|
-
|
|
574
|
+
// 0 is treated as the default 25% (2500 bps) so markets created before the
|
|
575
|
+
// field existed keep prior behavior (mirrors calculate_min_deposit_token_amount).
|
|
576
|
+
// withdrawCircuitBreakerBps is in basis points (BPS_PRECISION = 10_000 = 100%).
|
|
577
|
+
const breakerPct = spotMarket.withdrawCircuitBreakerBps === 0
|
|
578
|
+
? numericConstants_2.BPS_PRECISION.divn(4)
|
|
579
|
+
: new anchor_1.BN(spotMarket.withdrawCircuitBreakerBps);
|
|
580
|
+
const maxDrop = depositTokenTwapLive.mul(breakerPct).div(numericConstants_2.BPS_PRECISION);
|
|
581
|
+
const minDepositTokensTwap = depositTokenTwapLive.sub(anchor_1.BN.max(maxDrop, anchor_1.BN.min(spotMarket.withdrawGuardThreshold, depositTokenTwapLive)));
|
|
575
582
|
const { minDepositTokensForUtilization, maxBorrowTokensForUtilization } = calculateTokenUtilizationLimits(marketDepositTokenAmount, marketBorrowTokenAmount, spotMarket);
|
|
576
583
|
const minDepositTokens = anchor_1.BN.max(minDepositTokensForUtilization, minDepositTokensTwap);
|
|
577
584
|
let maxBorrowTokens = anchor_1.BN.min(maxBorrowTokensForUtilization, maxBorrowTokensTwap);
|
|
@@ -599,6 +606,40 @@ function calculateWithdrawLimit(spotMarket, now) {
|
|
|
599
606
|
};
|
|
600
607
|
}
|
|
601
608
|
exports.calculateWithdrawLimit = calculateWithdrawLimit;
|
|
609
|
+
/**
|
|
610
|
+
* Mirror of the program's `calculate_max_deposit_token_amount`. Returns the max
|
|
611
|
+
* resulting deposit token amount permitted by the daily deposit cap: growth up
|
|
612
|
+
* to `maxDepositBpsPerDay` above the 24h deposit TWAP, but never below the
|
|
613
|
+
* deposit guard threshold. Returns null when the cap is disabled (pct == 0).
|
|
614
|
+
*/
|
|
615
|
+
function calculateMaxDepositTokenAmount(depositTokenTwap, depositGuardThreshold, maxDepositBpsPerDay) {
|
|
616
|
+
if (maxDepositBpsPerDay === 0) {
|
|
617
|
+
return null; // disabled
|
|
618
|
+
}
|
|
619
|
+
// maxDepositBpsPerDay is in basis points (BPS_PRECISION = 10_000 = 100%).
|
|
620
|
+
const maxIncrease = depositTokenTwap
|
|
621
|
+
.mul(new anchor_1.BN(maxDepositBpsPerDay))
|
|
622
|
+
.div(numericConstants_2.BPS_PRECISION);
|
|
623
|
+
return anchor_1.BN.max(depositTokenTwap.add(maxIncrease), depositGuardThreshold);
|
|
624
|
+
}
|
|
625
|
+
exports.calculateMaxDepositTokenAmount = calculateMaxDepositTokenAmount;
|
|
626
|
+
/**
|
|
627
|
+
* Mirror of the program's `check_deposit_limits`. Returns true if the market's
|
|
628
|
+
* current deposit level is within the daily deposit cap (always true when the
|
|
629
|
+
* cap is disabled).
|
|
630
|
+
*/
|
|
631
|
+
function checkDepositLimits(spotMarket) {
|
|
632
|
+
if (spotMarket.maxDepositBpsPerDay === 0) {
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
const depositTokenAmount = getTokenAmount(spotMarket.depositBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
|
|
636
|
+
const maxDepositToken = calculateMaxDepositTokenAmount(spotMarket.depositTokenTwap, spotMarket.depositGuardThreshold, spotMarket.maxDepositBpsPerDay);
|
|
637
|
+
if (maxDepositToken === null) {
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
return depositTokenAmount.lte(maxDepositToken);
|
|
641
|
+
}
|
|
642
|
+
exports.checkDepositLimits = checkDepositLimits;
|
|
602
643
|
/**
|
|
603
644
|
* Calculates the margin-weighted value of a spot deposit, mirroring the asset-side of the
|
|
604
645
|
* program's collateral valuation (`get_strict_token_value` + `get_asset_weight`). Uses the
|
|
@@ -4,11 +4,22 @@ exports.TestClient = void 0;
|
|
|
4
4
|
const adminClient_1 = require("./adminClient");
|
|
5
5
|
class TestClient extends adminClient_1.AdminClient {
|
|
6
6
|
constructor(config) {
|
|
7
|
-
var _a;
|
|
7
|
+
var _a, _b, _c;
|
|
8
8
|
config.txVersion = 'legacy';
|
|
9
9
|
if (((_a = config.accountSubscription) === null || _a === void 0 ? void 0 : _a.type) !== 'polling') {
|
|
10
10
|
throw new Error('Test client must be polling');
|
|
11
11
|
}
|
|
12
|
+
// Blockhash caching keys its TTL off the wall clock, which is incompatible
|
|
13
|
+
// with bankrun's simulated clock: within a single 2s wall-clock window the
|
|
14
|
+
// bankrun validator advances many slots (and its blockhash), so a cached
|
|
15
|
+
// blockhash goes stale and sequential builds collide into identical
|
|
16
|
+
// transactions ("already processed") or reference an expired blockhash
|
|
17
|
+
// ("Blockhash not found"). There is also no real RPC to save in bankrun.
|
|
18
|
+
// Force fresh fetches unless a test explicitly opts back in.
|
|
19
|
+
config.txHandlerConfig = {
|
|
20
|
+
...config.txHandlerConfig,
|
|
21
|
+
blockhashCachingEnabled: (_c = (_b = config.txHandlerConfig) === null || _b === void 0 ? void 0 : _b.blockhashCachingEnabled) !== null && _c !== void 0 ? _c : false,
|
|
22
|
+
};
|
|
12
23
|
super(config);
|
|
13
24
|
}
|
|
14
25
|
async sendTransaction(tx, additionalSigners, opts, preSigned) {
|
|
@@ -37,7 +37,13 @@ export type TxBuildingProps = {
|
|
|
37
37
|
};
|
|
38
38
|
/** Configuration for `TxHandler`'s blockhash-fetching strategy. */
|
|
39
39
|
export type TxHandlerConfig = {
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Blockhash-fetching strategy. Defaults to `true`: a `CachedBlockhashFetcher`
|
|
42
|
+
* reuses a recent blockhash for `RECENT_BLOCKHASH_STALE_TIME_MS` (2s) to avoid a
|
|
43
|
+
* `getLatestBlockhash` RPC call on every transaction build — this is safe because a
|
|
44
|
+
* blockhash stays valid on-chain far longer than the cache TTL. Set to `false` to
|
|
45
|
+
* force a fresh RPC fetch on every build via `BaseBlockhashFetcher`.
|
|
46
|
+
*/
|
|
41
47
|
blockhashCachingEnabled?: boolean;
|
|
42
48
|
/** Tuning for `CachedBlockhashFetcher` when `blockhashCachingEnabled` is `true`; each field defaults if omitted (see `BLOCKHASH_FETCH_RETRY_COUNT`/`BLOCKHASH_FETCH_RETRY_SLEEP`/`RECENT_BLOCKHASH_STALE_TIME_MS`). */
|
|
43
49
|
blockhashCachingConfig?: {
|
|
@@ -64,9 +64,13 @@ class TxHandler {
|
|
|
64
64
|
this.confirmationOptions = props.confirmationOptions;
|
|
65
65
|
this.blockhashCommitment =
|
|
66
66
|
(_f = (_e = (_c = (_b = props.confirmationOptions) === null || _b === void 0 ? void 0 : _b.preflightCommitment) !== null && _c !== void 0 ? _c : (_d = props === null || props === void 0 ? void 0 : props.connection) === null || _d === void 0 ? void 0 : _d.commitment) !== null && _e !== void 0 ? _e : this.blockhashCommitment) !== null && _f !== void 0 ? _f : 'confirmed';
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
// Cache by default: only opt out when a consumer explicitly disables it. This
|
|
68
|
+
// collapses per-build `getLatestBlockhash` RPC calls (crankers dominate these)
|
|
69
|
+
// into at most one fetch per staleCacheTimeMs window.
|
|
70
|
+
this.blockHashFetcher =
|
|
71
|
+
((_g = props === null || props === void 0 ? void 0 : props.config) === null || _g === void 0 ? void 0 : _g.blockhashCachingEnabled) === false
|
|
72
|
+
? new baseBlockhashFetcher_1.BaseBlockhashFetcher(this.connection, this.blockhashCommitment)
|
|
73
|
+
: new cachedBlockhashFetcher_1.CachedBlockhashFetcher(this.connection, this.blockhashCommitment, (_k = (_j = (_h = props === null || props === void 0 ? void 0 : props.config) === null || _h === void 0 ? void 0 : _h.blockhashCachingConfig) === null || _j === void 0 ? void 0 : _j.retryCount) !== null && _k !== void 0 ? _k : BLOCKHASH_FETCH_RETRY_COUNT, (_o = (_m = (_l = props === null || props === void 0 ? void 0 : props.config) === null || _l === void 0 ? void 0 : _l.blockhashCachingConfig) === null || _m === void 0 ? void 0 : _m.retrySleepTimeMs) !== null && _o !== void 0 ? _o : BLOCKHASH_FETCH_RETRY_SLEEP, (_r = (_q = (_p = props === null || props === void 0 ? void 0 : props.config) === null || _p === void 0 ? void 0 : _p.blockhashCachingConfig) === null || _q === void 0 ? void 0 : _q.staleCacheTimeMs) !== null && _r !== void 0 ? _r : RECENT_BLOCKHASH_STALE_TIME_MS);
|
|
70
74
|
// #Optionals
|
|
71
75
|
this.returnBlockHeightsWithSignedTxCallbackData =
|
|
72
76
|
(_t = (_s = props.opts) === null || _s === void 0 ? void 0 : _s.returnBlockHeightsWithSignedTxCallbackData) !== null && _t !== void 0 ? _t : false;
|
package/lib/browser/types.d.ts
CHANGED
|
@@ -1207,6 +1207,8 @@ export type PerpMarketAccount = {
|
|
|
1207
1207
|
feePoolBufferTarget: BN;
|
|
1208
1208
|
/** PERCENTAGE_PRECISION (1e6 = 100%); fraction of OI notional (at the oracle TWAP) the sweep leaves behind in `feeLedger.pendingIfFee` as a standing bankruptcy first-loss tranche; 0 disables */
|
|
1209
1209
|
bankruptcyIfFloorPct: number;
|
|
1210
|
+
/** QUOTE_PRECISION (1e6); aggregate builder/referrer revenue share accrued but not yet paid out of this market's pnl pool. The fee sweep reserves it (like `max(net_user_pnl, 0)` and the floored IF tranche) so a protocol-fee drain can't leave accrued revenue-share claims temporarily unpayable */
|
|
1211
|
+
pendingRevenueShare: BN;
|
|
1210
1212
|
/** MARGIN_PRECISION (1e4); scales margin ratio up for large positions */
|
|
1211
1213
|
imfFactor: number;
|
|
1212
1214
|
/** MARGIN_PRECISION (1e4); discounts positive-unrealized-pnl asset weight for large positions */
|
|
@@ -1357,6 +1359,10 @@ export type SpotMarketAccount = {
|
|
|
1357
1359
|
protocolLiquidationFee: number;
|
|
1358
1360
|
/** IF_FACTOR_PRECISION (1e6); protocol's carveout of lending deposit-interest gains */
|
|
1359
1361
|
protocolFeeFactor: number;
|
|
1362
|
+
/** token mint precision; IF vault balance recorded at the last revenue settle, used as a
|
|
1363
|
+
* donation-proof base for the per-period revenue-settle APR cap (see `settle_revenue_to_insurance_fund`);
|
|
1364
|
+
* `0` = uninitialized (pre-upgrade accounts, seeded on first settle) */
|
|
1365
|
+
ifLastSettleVaultAmount: BN;
|
|
1360
1366
|
/** token mint decimals; token-mint precision throughout this account is 10^decimals */
|
|
1361
1367
|
decimals: number;
|
|
1362
1368
|
/** SPOT_UTILIZATION_PRECISION (1e6) */
|
|
@@ -1439,6 +1445,9 @@ export type SpotMarketAccount = {
|
|
|
1439
1445
|
poolId: number;
|
|
1440
1446
|
/** -100 to 100; percentage adjustment applied to the base fee rate */
|
|
1441
1447
|
feeAdjustment: number;
|
|
1448
|
+
depositGuardThreshold: BN;
|
|
1449
|
+
withdrawCircuitBreakerBps: number;
|
|
1450
|
+
maxDepositBpsPerDay: number;
|
|
1442
1451
|
};
|
|
1443
1452
|
/** A scaled token balance inside a market's internal pools (pnl pool, protocol fee pool, revenue pool, spot fee pool, AMM fee pool). Multiply `scaledBalance` (SPOT_BALANCE_PRECISION, 1e9) by the referenced spot market's `cumulativeDepositInterest`/`cumulativeBorrowInterest` to get the token amount. */
|
|
1444
1453
|
export type PoolBalance = {
|
package/lib/browser/user.d.ts
CHANGED
|
@@ -957,8 +957,8 @@ export declare class User {
|
|
|
957
957
|
getPerpPositionHealth({ marginCategory, perpPosition, oraclePriceData, quoteOraclePriceData, includeOpenOrders, }: {
|
|
958
958
|
marginCategory: MarginCategory;
|
|
959
959
|
perpPosition: PerpPosition;
|
|
960
|
-
oraclePriceData?: OraclePriceData
|
|
961
|
-
quoteOraclePriceData?: OraclePriceData
|
|
960
|
+
oraclePriceData?: Pick<OraclePriceData, 'price'>;
|
|
961
|
+
quoteOraclePriceData?: Pick<OraclePriceData, 'price'>;
|
|
962
962
|
includeOpenOrders?: boolean;
|
|
963
963
|
}): HealthComponent;
|
|
964
964
|
/**
|
|
@@ -10,6 +10,7 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
10
10
|
import { UserAccountFilterCriteria as UserFilterCriteria, UserMapConfig } from './userMapConfig';
|
|
11
11
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
13
|
+
export declare const USER_ACCOUNT_SIZE_BYTES = 4496;
|
|
13
14
|
/** Public surface implemented by `UserMap`. */
|
|
14
15
|
export interface UserMapInterface {
|
|
15
16
|
eventEmitter: StrictEventEmitter<EventEmitter, UserEvents>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UserMap = void 0;
|
|
3
|
+
exports.UserMap = exports.USER_ACCOUNT_SIZE_BYTES = void 0;
|
|
4
4
|
const user_1 = require("../user");
|
|
5
5
|
const DLOB_1 = require("../dlob/DLOB");
|
|
6
6
|
const oneShotUserAccountSubscriber_1 = require("../accounts/oneShotUserAccountSubscriber");
|
|
@@ -13,11 +13,7 @@ const PollingSubscription_1 = require("./PollingSubscription");
|
|
|
13
13
|
const user_2 = require("../decode/user");
|
|
14
14
|
const grpcSubscription_1 = require("./grpcSubscription");
|
|
15
15
|
const events_1 = require("events");
|
|
16
|
-
|
|
17
|
-
// drift's was 4376. This caps the zstd-decompressed buffer in defaultSync — if it's
|
|
18
|
-
// smaller than the real account, the buffer is truncated and decodeUser reads past
|
|
19
|
-
// the end (RangeError: ERR_BUFFER_OUT_OF_BOUNDS). Must be >= the on-chain User size.
|
|
20
|
-
const MAX_USER_ACCOUNT_SIZE_BYTES = 4496;
|
|
16
|
+
exports.USER_ACCOUNT_SIZE_BYTES = 4496;
|
|
21
17
|
/**
|
|
22
18
|
* In-memory cache of every `User` account on the program, keyed by the
|
|
23
19
|
* `User` account's own public key.
|
|
@@ -393,7 +389,7 @@ class UserMap {
|
|
|
393
389
|
const compressedUserData = buffer_1.Buffer.from(programAccount.account.data[0], 'base64');
|
|
394
390
|
const decoder = new zstddec_1.ZSTDDecoder();
|
|
395
391
|
await decoder.init();
|
|
396
|
-
const userBuffer = decoder.decode(compressedUserData,
|
|
392
|
+
const userBuffer = decoder.decode(compressedUserData, exports.USER_ACCOUNT_SIZE_BYTES);
|
|
397
393
|
programAccountBufferMap.set(programAccount.pubkey.toString(), buffer_1.Buffer.from(userBuffer));
|
|
398
394
|
});
|
|
399
395
|
await Promise.all(decodingPromises);
|
|
@@ -433,25 +433,24 @@ export declare class VelocityClient {
|
|
|
433
433
|
externalWallet?: PublicKey;
|
|
434
434
|
}): Promise<[PublicKey, TransactionInstruction]>;
|
|
435
435
|
/**
|
|
436
|
-
*
|
|
437
|
-
* only
|
|
436
|
+
* Resizes an existing `SignedMsgUserOrders` account. Growing (adding order-message slots) is
|
|
437
|
+
* permitted for any payer; shrinking is only permitted when the payer is the account's
|
|
438
|
+
* `authority`, because the account is authority-scoped and shared across all of the authority's
|
|
439
|
+
* subaccounts — a shrink evicts replay-protection UUIDs for every subaccount.
|
|
438
440
|
* @param authority - Authority whose account is resized.
|
|
439
|
-
* @param numOrders - New
|
|
440
|
-
* @param userSubaccountId - Sub-account id used to derive the `user` account passed to the
|
|
441
|
-
* instruction; defaults to `0`.
|
|
441
|
+
* @param numOrders - New number of order-message slots.
|
|
442
442
|
* @param txParams - Optional compute-unit/priority-fee overrides for the transaction.
|
|
443
443
|
* @returns The transaction signature.
|
|
444
444
|
*/
|
|
445
|
-
resizeSignedMsgUserOrders(authority: PublicKey, numOrders: number,
|
|
445
|
+
resizeSignedMsgUserOrders(authority: PublicKey, numOrders: number, txParams?: TxParams): Promise<TransactionSignature>;
|
|
446
446
|
/**
|
|
447
447
|
* Builds the `resizeSignedMsgUserOrders` instruction. See `resizeSignedMsgUserOrders` for
|
|
448
448
|
* semantics.
|
|
449
449
|
* @param authority - Authority whose account is resized.
|
|
450
|
-
* @param numOrders - New
|
|
451
|
-
* @param userSubaccountId - Sub-account id used to derive the `user` account; defaults to `0`.
|
|
450
|
+
* @param numOrders - New number of order-message slots.
|
|
452
451
|
* @returns The resize instruction.
|
|
453
452
|
*/
|
|
454
|
-
getResizeSignedMsgUserOrdersInstruction(authority: PublicKey, numOrders: number
|
|
453
|
+
getResizeSignedMsgUserOrdersInstruction(authority: PublicKey, numOrders: number): Promise<TransactionInstruction>;
|
|
455
454
|
/**
|
|
456
455
|
* Initializes `authority`'s `SignedMsgWsDelegates` account, which lists wallets authorized to
|
|
457
456
|
* co-sign/relay that authority's signed-message ("swift") orders over a websocket connection
|
|
@@ -1574,9 +1573,11 @@ export declare class VelocityClient {
|
|
|
1574
1573
|
* @param fromSubAccountId - Sub-account id to debit.
|
|
1575
1574
|
* @param toSubAccountId - Sub-account id to credit.
|
|
1576
1575
|
* @param equityFloorDelta - Equity floor (QUOTE_PRECISION) to move from the debited to the credited
|
|
1577
|
-
* sub-account along with the funds, keeping the sum of floors constant. The debited side must
|
|
1578
|
-
*
|
|
1579
|
-
*
|
|
1576
|
+
* sub-account along with the funds, keeping the sum of floors constant. The debited side must not
|
|
1577
|
+
* already be below the floor being reduced (a below-floor sub-account cannot shed floor to defuse a
|
|
1578
|
+
* pending equity-breaker trip), must stay at/above its reduced floor, and the credited side's
|
|
1579
|
+
* collateral (after the transfer lands) must back its increased floor, else the transfer reverts with
|
|
1580
|
+
* `InvalidEquityFloorTransfer`. Pass `'auto'`
|
|
1580
1581
|
* (quote market only) to move the minimal floor needed for the debited side to stay at/above its
|
|
1581
1582
|
* floor: `max(0, amount - (collateral - floor))`, capped at the debited side's floor. The auto delta
|
|
1582
1583
|
* never exceeds `amount`, so the credited side stays backed whenever it was before. Client-side
|
|
@@ -3220,7 +3221,8 @@ export declare class VelocityClient {
|
|
|
3220
3221
|
* position to the calling liquidator's sub-account at the oracle price (subject to `limitPrice`
|
|
3221
3222
|
* and the on-chain liquidation fee). Reverts if `userAccountPublicKey` equals the liquidator's
|
|
3222
3223
|
* own user account. Permissionless — any signer can act as liquidator, taking on the position
|
|
3223
|
-
* and its PnL themselves.
|
|
3224
|
+
* and its PnL themselves. Reverts with `EquityBelowFloor` if the liquidator's authority-wide
|
|
3225
|
+
* equity breaker is tripped (a tripped authority is barred from position-acquiring liquidations).
|
|
3224
3226
|
* @param userAccountPublicKey - Public key of the user account being liquidated.
|
|
3225
3227
|
* @param userAccount - Decoded user account being liquidated.
|
|
3226
3228
|
* @param marketIndex - Perp market index of the position to liquidate.
|
|
@@ -3272,7 +3274,9 @@ export declare class VelocityClient {
|
|
|
3272
3274
|
* debt from the user to the liquidator's own sub-account in exchange for `assetMarketIndex`
|
|
3273
3275
|
* collateral, when the user is below maintenance margin (or already flagged `beingLiquidated`).
|
|
3274
3276
|
* Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless —
|
|
3275
|
-
* any signer can act as liquidator.
|
|
3277
|
+
* any signer can act as liquidator. Reverts with `EquityBelowFloor` if the liquidator's
|
|
3278
|
+
* authority-wide equity breaker is tripped (a tripped authority is barred from position-acquiring
|
|
3279
|
+
* liquidations).
|
|
3276
3280
|
* @param userAccountPublicKey - Public key of the user account being liquidated.
|
|
3277
3281
|
* @param userAccount - Decoded user account being liquidated.
|
|
3278
3282
|
* @param assetMarketIndex - Spot market index of the collateral the liquidator receives.
|
|
@@ -3381,7 +3385,9 @@ export declare class VelocityClient {
|
|
|
3381
3385
|
* PnL in `perpMarketIndex`. Only usable once the user's position size in `perpMarketIndex` is
|
|
3382
3386
|
* zero (the PnL must already be fully unrealized/settled-out, not backed by an open position).
|
|
3383
3387
|
* Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless —
|
|
3384
|
-
* any signer can act as liquidator.
|
|
3388
|
+
* any signer can act as liquidator. Reverts with `EquityBelowFloor` if the liquidator's
|
|
3389
|
+
* authority-wide equity breaker is tripped (a tripped authority is barred from
|
|
3390
|
+
* balance-acquiring liquidations).
|
|
3385
3391
|
* @param userAccountPublicKey - Public key of the user account being liquidated.
|
|
3386
3392
|
* @param userAccount - Decoded user account being liquidated.
|
|
3387
3393
|
* @param perpMarketIndex - Perp market index whose unsettled PnL backs the transfer, QUOTE_PRECISION (1e6).
|
|
@@ -3412,7 +3418,9 @@ export declare class VelocityClient {
|
|
|
3412
3418
|
* `perpMarketIndex` from the user to the liquidator in exchange for `assetMarketIndex` spot
|
|
3413
3419
|
* collateral (the inverse of `liquidateBorrowForPerpPnl`). Only usable once the user's position
|
|
3414
3420
|
* size in `perpMarketIndex` is zero. Reverts if `userAccountPublicKey` equals the liquidator's
|
|
3415
|
-
* own user account. Permissionless — any signer can act as liquidator.
|
|
3421
|
+
* own user account. Permissionless — any signer can act as liquidator. Reverts with
|
|
3422
|
+
* `EquityBelowFloor` if the liquidator's authority-wide equity breaker is tripped (a tripped
|
|
3423
|
+
* authority is barred from balance-acquiring liquidations).
|
|
3416
3424
|
* @param userAccountPublicKey - Public key of the user account being liquidated.
|
|
3417
3425
|
* @param userAccount - Decoded user account being liquidated.
|
|
3418
3426
|
* @param perpMarketIndex - Perp market index of the negative unsettled PnL being absorbed.
|
|
@@ -3693,8 +3701,10 @@ export declare class VelocityClient {
|
|
|
3693
3701
|
}): Promise<TransactionInstruction[]>;
|
|
3694
3702
|
/**
|
|
3695
3703
|
* Starts the unstaking cooldown for this wallet's insurance fund stake in `marketIndex`, locking
|
|
3696
|
-
* in the number of IF shares corresponding to `amount` at the current share price.
|
|
3697
|
-
*
|
|
3704
|
+
* in the number of IF shares corresponding to `amount` at the current share price. Any revenue
|
|
3705
|
+
* already due to the insurance fund is settled first (mirroring `addInsuranceFundStake`), so the
|
|
3706
|
+
* frozen exit value includes the staker's share of it rather than forfeiting it to the remaining
|
|
3707
|
+
* stakers. The actual withdrawal must be completed with `removeInsuranceFundStake` after
|
|
3698
3708
|
* `spotMarket.insuranceFund.unstakingPeriod` seconds have elapsed; only one request may be
|
|
3699
3709
|
* in-flight per stake account (`cancelRequestRemoveInsuranceFundStake` to reset). A caller may
|
|
3700
3710
|
* only act on their own stake account.
|
|
@@ -3770,8 +3780,10 @@ export declare class VelocityClient {
|
|
|
3770
3780
|
* `pendingAmmProvision` into the AMM's fee pool (both leave `feePoolBufferTarget` behind). Every
|
|
3771
3781
|
* drain reserves `max(netUserPnl, 0)` so user claims stay backed. This runs inline on every
|
|
3772
3782
|
* `settlePNL` already — this instruction lets a keeper run it on demand without settling anyone's
|
|
3773
|
-
* PnL.
|
|
3774
|
-
*
|
|
3783
|
+
* PnL. Values `netUserPnl` at the market's fixed `expiryPrice` when the market is in `settlement`
|
|
3784
|
+
* status (expired positions settle at that price, not the live oracle, so no live-oracle gate is
|
|
3785
|
+
* applied); otherwise it uses the live oracle price and gates it the same way `settlePNL` does
|
|
3786
|
+
* (price-band + validity/divergence checks when the market has curve updates enabled).
|
|
3775
3787
|
* @param perpMarketIndex - Perp market index to sweep fees for.
|
|
3776
3788
|
* @param txParams - Optional compute-unit/priority-fee overrides.
|
|
3777
3789
|
* @returns The transaction signature.
|