@velocity-exchange/sdk 0.6.0 → 0.7.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 +17 -0
- package/lib/browser/adminClient.js +32 -0
- 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/idl/velocity.d.ts +46 -13
- package/lib/browser/idl/velocity.json +46 -13
- package/lib/browser/math/amm.d.ts +8 -8
- package/lib/browser/math/funding.d.ts +2 -2
- 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/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.js +7 -4
- 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 +2 -0
- package/lib/browser/user.d.ts +7 -5
- package/lib/browser/user.js +15 -3
- package/lib/browser/userMap/userMap.d.ts +1 -0
- package/lib/browser/userMap/userMap.js +3 -7
- package/lib/node/adminClient.d.ts +17 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +32 -0
- 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/idl/velocity.d.ts +46 -13
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +46 -13
- 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/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/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +7 -4
- 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 +2 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +7 -5
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +15 -3
- 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/package.json +1 -1
|
@@ -1533,6 +1533,23 @@ export declare class AdminClient extends VelocityClient {
|
|
|
1533
1533
|
* @returns The unsigned `updatePerpMarketFeePoolBufferTarget` instruction.
|
|
1534
1534
|
*/
|
|
1535
1535
|
getUpdatePerpMarketFeePoolBufferTargetIx(perpMarketIndex: number, feePoolBufferTarget: BN): Promise<TransactionInstruction>;
|
|
1536
|
+
/**
|
|
1537
|
+
* Sets the fraction of open-interest notional the streaming fee sweep must leave behind in
|
|
1538
|
+
* `feeLedger.pendingIfFee` as a standing bankruptcy tranche (notional valued at the market's
|
|
1539
|
+
* oracle TWAP). The permissionless sweep cannot drain the tranche below this floor, so a
|
|
1540
|
+
* sweep front-running a `resolvePerpBankruptcy` cannot strip the first-loss coverage up to
|
|
1541
|
+
* the floor. New markets initialize to 10 bps; 0 disables. Requires warm admin (`check_warm`).
|
|
1542
|
+
* @param perpMarketIndex - Perp market to update.
|
|
1543
|
+
* @param bankruptcyIfFloorPct - Floor as PERCENTAGE_PRECISION (1e6 = 100%; 1000 = 10 bps); max 1e6.
|
|
1544
|
+
* @returns Transaction signature.
|
|
1545
|
+
*/
|
|
1546
|
+
updatePerpMarketBankruptcyIfFloorPct(perpMarketIndex: number, bankruptcyIfFloorPct: number): Promise<TransactionSignature>;
|
|
1547
|
+
/**
|
|
1548
|
+
* Builds the `updatePerpMarketBankruptcyIfFloorPct` instruction without sending it. See
|
|
1549
|
+
* `updatePerpMarketBankruptcyIfFloorPct`.
|
|
1550
|
+
* @returns The unsigned `updatePerpMarketBankruptcyIfFloorPct` instruction.
|
|
1551
|
+
*/
|
|
1552
|
+
getUpdatePerpMarketBankruptcyIfFloorPctIx(perpMarketIndex: number, bankruptcyIfFloorPct: number): Promise<TransactionInstruction>;
|
|
1536
1553
|
/**
|
|
1537
1554
|
* Scales a spot market's taker fee and maker rebate up or down by a percentage of the base
|
|
1538
1555
|
* fee tier. Requires warm admin (`check_warm`). Throws `DefaultError` on-chain if
|
|
@@ -3015,6 +3015,38 @@ class AdminClient extends velocityClient_1.VelocityClient {
|
|
|
3015
3015
|
},
|
|
3016
3016
|
});
|
|
3017
3017
|
}
|
|
3018
|
+
/**
|
|
3019
|
+
* Sets the fraction of open-interest notional the streaming fee sweep must leave behind in
|
|
3020
|
+
* `feeLedger.pendingIfFee` as a standing bankruptcy tranche (notional valued at the market's
|
|
3021
|
+
* oracle TWAP). The permissionless sweep cannot drain the tranche below this floor, so a
|
|
3022
|
+
* sweep front-running a `resolvePerpBankruptcy` cannot strip the first-loss coverage up to
|
|
3023
|
+
* the floor. New markets initialize to 10 bps; 0 disables. Requires warm admin (`check_warm`).
|
|
3024
|
+
* @param perpMarketIndex - Perp market to update.
|
|
3025
|
+
* @param bankruptcyIfFloorPct - Floor as PERCENTAGE_PRECISION (1e6 = 100%; 1000 = 10 bps); max 1e6.
|
|
3026
|
+
* @returns Transaction signature.
|
|
3027
|
+
*/
|
|
3028
|
+
async updatePerpMarketBankruptcyIfFloorPct(perpMarketIndex, bankruptcyIfFloorPct) {
|
|
3029
|
+
const updatePerpMarketBankruptcyIfFloorPctIx = await this.getUpdatePerpMarketBankruptcyIfFloorPctIx(perpMarketIndex, bankruptcyIfFloorPct);
|
|
3030
|
+
const tx = await this.buildTransaction(updatePerpMarketBankruptcyIfFloorPctIx);
|
|
3031
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
3032
|
+
return txSig;
|
|
3033
|
+
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Builds the `updatePerpMarketBankruptcyIfFloorPct` instruction without sending it. See
|
|
3036
|
+
* `updatePerpMarketBankruptcyIfFloorPct`.
|
|
3037
|
+
* @returns The unsigned `updatePerpMarketBankruptcyIfFloorPct` instruction.
|
|
3038
|
+
*/
|
|
3039
|
+
async getUpdatePerpMarketBankruptcyIfFloorPctIx(perpMarketIndex, bankruptcyIfFloorPct) {
|
|
3040
|
+
return await this.program.instruction.updatePerpMarketBankruptcyIfFloorPct(bankruptcyIfFloorPct, {
|
|
3041
|
+
accounts: {
|
|
3042
|
+
admin: this.isSubscribed
|
|
3043
|
+
? this.getStateAccount().coldAdmin
|
|
3044
|
+
: this.wallet.publicKey,
|
|
3045
|
+
state: await this.getStatePublicKey(),
|
|
3046
|
+
perpMarket: await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, perpMarketIndex),
|
|
3047
|
+
},
|
|
3048
|
+
});
|
|
3049
|
+
}
|
|
3018
3050
|
/**
|
|
3019
3051
|
* Scales a spot market's taker fee and maker rebate up or down by a percentage of the base
|
|
3020
3052
|
* fee tier. Requires warm admin (`check_warm`). Throws `DefaultError` on-chain if
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { BlockhashWithExpiryBlockHeight, Context } from '@solana/web3.js';
|
|
2
2
|
import { BlockhashSubscriberConfig } from './types';
|
|
3
3
|
/**
|
|
4
|
-
* BlockhashSubscriber — polls `getLatestBlockhashAndContext
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* (
|
|
9
|
-
*
|
|
4
|
+
* BlockhashSubscriber — polls `getLatestBlockhashAndContext` on a fixed
|
|
5
|
+
* interval and caches a short history of recent blockhashes, so callers can
|
|
6
|
+
* grab a recent blockhash for transaction building without an RPC round-trip
|
|
7
|
+
* per transaction. The current block height is derived from the same response
|
|
8
|
+
* (`lastValidBlockHeight - 150`), so no paired `getBlockHeight` call is made.
|
|
9
|
+
* Nothing is populated until `subscribe()` (or a manual `updateBlockhash()`)
|
|
10
|
+
* has completed at least once — all getters return `undefined`/empty before
|
|
11
|
+
* then.
|
|
10
12
|
*/
|
|
11
13
|
export declare class BlockhashSubscriber {
|
|
12
14
|
private connection;
|
|
@@ -28,9 +30,9 @@ export declare class BlockhashSubscriber {
|
|
|
28
30
|
* @returns The block height as of the most recent successful poll, or
|
|
29
31
|
* `undefined` if `subscribe()`/`updateBlockhash()` has not yet completed
|
|
30
32
|
* successfully at least once (including if every poll so far has errored).
|
|
31
|
-
* This value is
|
|
32
|
-
*
|
|
33
|
-
* blockhash slot, only "recent as of the last poll".
|
|
33
|
+
* This value is derived from the latest blockhash fetch
|
|
34
|
+
* (`lastValidBlockHeight - 150`) — it is not guaranteed to be perfectly in
|
|
35
|
+
* sync with the blockhash slot, only "recent as of the last poll".
|
|
34
36
|
*/
|
|
35
37
|
getLatestBlockHeight(): number | undefined;
|
|
36
38
|
/** @returns The RPC `Context` (including `slot`) captured with the most recent successful blockhash poll, or `undefined` before the first successful poll. */
|
|
@@ -45,12 +47,14 @@ export declare class BlockhashSubscriber {
|
|
|
45
47
|
/** Drops cached blockhashes whose `lastValidBlockHeight` is at or below `latestBlockHeight` (i.e. already expired for transaction signing). Called automatically after every `updateBlockhash`. No-ops if `latestBlockHeight` hasn't been set yet. */
|
|
46
48
|
pruneBlockhashes(): void;
|
|
47
49
|
/**
|
|
48
|
-
* Fetches the latest blockhash and
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* `
|
|
50
|
+
* Fetches the latest blockhash and appends it to the cache (skipped if it's
|
|
51
|
+
* identical to the most-recently-cached one), then prunes expired entries.
|
|
52
|
+
* The current block height is derived from the same response
|
|
53
|
+
* (`lastValidBlockHeight - 150`) rather than a paired `getBlockHeight` call.
|
|
54
|
+
* Errors (e.g. RPC failure) are caught and logged, not thrown — on error,
|
|
55
|
+
* `latestBlockHeight` is left at its previous value, but `pruneBlockhashes()`
|
|
56
|
+
* still runs in a `finally` block and may evict entries that expired in the
|
|
57
|
+
* meantime.
|
|
54
58
|
*/
|
|
55
59
|
updateBlockhash(): Promise<void>;
|
|
56
60
|
/** Performs an immediate `updateBlockhash()` and then starts polling on `updateIntervalMs`. Idempotent — a second call while already subscribed is a no-op. */
|
|
@@ -3,12 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BlockhashSubscriber = void 0;
|
|
4
4
|
const web3_js_1 = require("@solana/web3.js");
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
* A blockhash is valid for signing until 150 blocks after the block it was
|
|
7
|
+
* fetched from, so `getLatestBlockhash`'s `lastValidBlockHeight` is exactly
|
|
8
|
+
* `(block height of that blockhash) + 150`. Subtracting this offset recovers
|
|
9
|
+
* the current block height without a second RPC call.
|
|
10
|
+
*/
|
|
11
|
+
const BLOCKHASH_VALIDITY_BLOCKS = 150;
|
|
12
|
+
/**
|
|
13
|
+
* BlockhashSubscriber — polls `getLatestBlockhashAndContext` on a fixed
|
|
14
|
+
* interval and caches a short history of recent blockhashes, so callers can
|
|
15
|
+
* grab a recent blockhash for transaction building without an RPC round-trip
|
|
16
|
+
* per transaction. The current block height is derived from the same response
|
|
17
|
+
* (`lastValidBlockHeight - 150`), so no paired `getBlockHeight` call is made.
|
|
18
|
+
* Nothing is populated until `subscribe()` (or a manual `updateBlockhash()`)
|
|
19
|
+
* has completed at least once — all getters return `undefined`/empty before
|
|
20
|
+
* then.
|
|
12
21
|
*/
|
|
13
22
|
class BlockhashSubscriber {
|
|
14
23
|
/**
|
|
@@ -34,9 +43,9 @@ class BlockhashSubscriber {
|
|
|
34
43
|
* @returns The block height as of the most recent successful poll, or
|
|
35
44
|
* `undefined` if `subscribe()`/`updateBlockhash()` has not yet completed
|
|
36
45
|
* successfully at least once (including if every poll so far has errored).
|
|
37
|
-
* This value is
|
|
38
|
-
*
|
|
39
|
-
* blockhash slot, only "recent as of the last poll".
|
|
46
|
+
* This value is derived from the latest blockhash fetch
|
|
47
|
+
* (`lastValidBlockHeight - 150`) — it is not guaranteed to be perfectly in
|
|
48
|
+
* sync with the blockhash slot, only "recent as of the last poll".
|
|
40
49
|
*/
|
|
41
50
|
getLatestBlockHeight() {
|
|
42
51
|
return this.latestBlockHeight;
|
|
@@ -69,22 +78,22 @@ class BlockhashSubscriber {
|
|
|
69
78
|
}
|
|
70
79
|
}
|
|
71
80
|
/**
|
|
72
|
-
* Fetches the latest blockhash and
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* `
|
|
81
|
+
* Fetches the latest blockhash and appends it to the cache (skipped if it's
|
|
82
|
+
* identical to the most-recently-cached one), then prunes expired entries.
|
|
83
|
+
* The current block height is derived from the same response
|
|
84
|
+
* (`lastValidBlockHeight - 150`) rather than a paired `getBlockHeight` call.
|
|
85
|
+
* Errors (e.g. RPC failure) are caught and logged, not thrown — on error,
|
|
86
|
+
* `latestBlockHeight` is left at its previous value, but `pruneBlockhashes()`
|
|
87
|
+
* still runs in a `finally` block and may evict entries that expired in the
|
|
88
|
+
* meantime.
|
|
78
89
|
*/
|
|
79
90
|
async updateBlockhash() {
|
|
80
91
|
try {
|
|
81
|
-
const
|
|
82
|
-
this.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
]);
|
|
87
|
-
this.latestBlockHeight = lastConfirmedBlockHeight;
|
|
92
|
+
const resp = await this.connection.getLatestBlockhashAndContext({
|
|
93
|
+
commitment: this.commitment,
|
|
94
|
+
});
|
|
95
|
+
this.latestBlockHeight =
|
|
96
|
+
resp.value.lastValidBlockHeight - BLOCKHASH_VALIDITY_BLOCKS;
|
|
88
97
|
this.latestBlockHeightContext = resp.context;
|
|
89
98
|
// avoid caching duplicate blockhashes
|
|
90
99
|
if (this.blockhashes.length > 0) {
|
|
@@ -102,6 +102,8 @@ export declare const FUNDING_RATE_CLAMP_DENOMINATOR: BN;
|
|
|
102
102
|
export declare const PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO: BN;
|
|
103
103
|
/** 300 seconds. */
|
|
104
104
|
export declare const FIVE_MINUTE: BN;
|
|
105
|
+
/** Max age of the last fill before the trigger price's last-fill leg is treated as absent (oracle price substitutes). */
|
|
106
|
+
export declare const TRIGGER_PRICE_LAST_FILL_MAX_AGE: BN;
|
|
105
107
|
/** 3600 seconds. */
|
|
106
108
|
export declare const ONE_HOUR: BN;
|
|
107
109
|
/** 31,536,000 seconds (365 days). */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.PRICE_DIV_PEG = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_RATE_BUFFER_PRECISION = exports.FUNDING_RATE_PRECISION = exports.PRICE_PRECISION = exports.QUOTE_PRECISION = exports.LIQUIDATION_FEE_PRECISION = exports.SPOT_MARKET_IMF_PRECISION = exports.SPOT_MARKET_IMF_PRECISION_EXP = exports.SPOT_MARKET_BALANCE_PRECISION = exports.SPOT_MARKET_BALANCE_PRECISION_EXP = exports.SPOT_MARKET_WEIGHT_PRECISION = exports.SPOT_MARKET_UTILIZATION_PRECISION = exports.SPOT_MARKET_UTILIZATION_PRECISION_EXP = exports.SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION = exports.SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION_EXP = exports.SPOT_MARKET_RATE_PRECISION = exports.SPOT_MARKET_RATE_PRECISION_EXP = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.PRICE_PRECISION_EXP = exports.FUNDING_RATE_BUFFER_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.CONCENTRATION_PRECISION = exports.PERCENTAGE_PRECISION = exports.PERCENTAGE_PRECISION_EXP = exports.MAX_LEVERAGE_ORDER_SIZE = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.NINE = exports.EIGHT = exports.SEVEN = exports.SIX = exports.FIVE = exports.FOUR = exports.THREE = exports.TWO = exports.ONE = exports.ZERO = void 0;
|
|
4
|
-
exports.MIN_I64 = exports.MAX_I64 = exports.GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = exports.MAX_POSITIVE_UPNL_FOR_INITIAL_MARGIN = exports.DUST_POSITION_SIZE = exports.SLOT_TIME_ESTIMATE_MS = exports.IDLE_TIME_SLOTS = exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = exports.DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT = exports.OPEN_ORDER_MARGIN_REQUIREMENT = exports.LAMPORTS_EXP = exports.LAMPORTS_PRECISION = exports.QUOTE_SPOT_MARKET_INDEX = exports.ONE_YEAR = exports.ONE_HOUR = exports.FIVE_MINUTE = exports.PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = exports.FUNDING_RATE_CLAMP_DENOMINATOR = exports.FUNDING_RATE_OFFSET_PERCENTAGE = exports.FUNDING_RATE_OFFSET_DENOMINATOR = exports.LIQUIDATION_PCT_PRECISION = exports.BID_ASK_SPREAD_PRECISION = exports.BPS_PRECISION = void 0;
|
|
4
|
+
exports.MIN_I64 = exports.MAX_I64 = exports.GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = exports.MAX_POSITIVE_UPNL_FOR_INITIAL_MARGIN = exports.DUST_POSITION_SIZE = exports.SLOT_TIME_ESTIMATE_MS = exports.IDLE_TIME_SLOTS = exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = exports.DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT = exports.OPEN_ORDER_MARGIN_REQUIREMENT = exports.LAMPORTS_EXP = exports.LAMPORTS_PRECISION = exports.QUOTE_SPOT_MARKET_INDEX = exports.ONE_YEAR = exports.ONE_HOUR = exports.TRIGGER_PRICE_LAST_FILL_MAX_AGE = exports.FIVE_MINUTE = exports.PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = exports.FUNDING_RATE_CLAMP_DENOMINATOR = exports.FUNDING_RATE_OFFSET_PERCENTAGE = exports.FUNDING_RATE_OFFSET_DENOMINATOR = exports.LIQUIDATION_PCT_PRECISION = exports.BID_ASK_SPREAD_PRECISION = exports.BPS_PRECISION = void 0;
|
|
5
5
|
const web3_js_1 = require("@solana/web3.js");
|
|
6
6
|
const anchor_1 = require("../isomorphic/anchor");
|
|
7
7
|
/** Precision constants used throughout the SDK. Each mirrors an on-chain fixed-point scale — a raw `BN` amount at that precision represents `amount / 10^exponent` in human units (e.g. `PRICE_PRECISION` = 1e6, so a raw price of `1_500_000` is `$1.50`). Values must stay numerically identical to the Rust program's `math::constants` — a mismatch here silently mis-scales every derived SDK computation. */
|
|
@@ -107,6 +107,8 @@ exports.FUNDING_RATE_CLAMP_DENOMINATOR = new anchor_1.BN(2000);
|
|
|
107
107
|
exports.PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = exports.PRICE_PRECISION.mul(exports.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
108
108
|
/** 300 seconds. */
|
|
109
109
|
exports.FIVE_MINUTE = new anchor_1.BN(60 * 5);
|
|
110
|
+
/** Max age of the last fill before the trigger price's last-fill leg is treated as absent (oracle price substitutes). */
|
|
111
|
+
exports.TRIGGER_PRICE_LAST_FILL_MAX_AGE = exports.FIVE_MINUTE;
|
|
110
112
|
/** 3600 seconds. */
|
|
111
113
|
exports.ONE_HOUR = new anchor_1.BN(60 * 60);
|
|
112
114
|
/** 31,536,000 seconds (365 days). */
|
|
@@ -8,7 +8,7 @@ export type Velocity = {
|
|
|
8
8
|
"address": "vELoC1audYbSYVRXn1vPaV8Axoa9oU6BYmNGZZBDZ1P";
|
|
9
9
|
"metadata": {
|
|
10
10
|
"name": "velocity";
|
|
11
|
-
"version": "2.163.
|
|
11
|
+
"version": "2.163.1";
|
|
12
12
|
"spec": "0.1.0";
|
|
13
13
|
"description": "Created with Anchor";
|
|
14
14
|
};
|
|
@@ -9678,6 +9678,38 @@ export type Velocity = {
|
|
|
9678
9678
|
}
|
|
9679
9679
|
];
|
|
9680
9680
|
},
|
|
9681
|
+
{
|
|
9682
|
+
"name": "updatePerpMarketBankruptcyIfFloorPct";
|
|
9683
|
+
"discriminator": [
|
|
9684
|
+
192,
|
|
9685
|
+
2,
|
|
9686
|
+
229,
|
|
9687
|
+
220,
|
|
9688
|
+
243,
|
|
9689
|
+
115,
|
|
9690
|
+
121,
|
|
9691
|
+
84
|
|
9692
|
+
];
|
|
9693
|
+
"accounts": [
|
|
9694
|
+
{
|
|
9695
|
+
"name": "admin";
|
|
9696
|
+
"signer": true;
|
|
9697
|
+
},
|
|
9698
|
+
{
|
|
9699
|
+
"name": "state";
|
|
9700
|
+
},
|
|
9701
|
+
{
|
|
9702
|
+
"name": "perpMarket";
|
|
9703
|
+
"writable": true;
|
|
9704
|
+
}
|
|
9705
|
+
];
|
|
9706
|
+
"args": [
|
|
9707
|
+
{
|
|
9708
|
+
"name": "bankruptcyIfFloorPct";
|
|
9709
|
+
"type": "u32";
|
|
9710
|
+
}
|
|
9711
|
+
];
|
|
9712
|
+
},
|
|
9681
9713
|
{
|
|
9682
9714
|
"name": "updatePerpMarketBaseSpread";
|
|
9683
9715
|
"discriminator": [
|
|
@@ -21146,20 +21178,21 @@ export type Velocity = {
|
|
|
21146
21178
|
"type": "i8";
|
|
21147
21179
|
},
|
|
21148
21180
|
{
|
|
21149
|
-
"name": "
|
|
21181
|
+
"name": "bankruptcyIfFloorPct";
|
|
21150
21182
|
"docs": [
|
|
21151
|
-
"
|
|
21152
|
-
"
|
|
21153
|
-
"
|
|
21154
|
-
"
|
|
21155
|
-
"
|
|
21183
|
+
"Floor on the unswept IF-fee carveout, as a percentage of open-interest",
|
|
21184
|
+
"notional (PERCENTAGE_PRECISION; 0 disables). The fee sweep's IF drain",
|
|
21185
|
+
"leaves `pending_if_fee` at (at least) this floor, so a standing",
|
|
21186
|
+
"first-loss tranche is always available to `resolve_perp_bankruptcy` —",
|
|
21187
|
+
"a permissionless sweep (or the inline sweep on any pnl settle) cannot",
|
|
21188
|
+
"drain the tranche below it ahead of a bankruptcy resolution. Notional",
|
|
21189
|
+
"is valued at the market's own oracle TWAP so a manipulated spot print",
|
|
21190
|
+
"can't crush the floor. Occupies the former 4-byte trailing padding",
|
|
21191
|
+
"before `market_stats` (same offset/alignment on all targets), so",
|
|
21192
|
+
"existing accounts read 0 = disabled until the admin sets it;",
|
|
21193
|
+
"new markets initialize to `DEFAULT_BANKRUPTCY_IF_FLOOR_PCT`."
|
|
21156
21194
|
];
|
|
21157
|
-
"type":
|
|
21158
|
-
"array": [
|
|
21159
|
-
"u8",
|
|
21160
|
-
4
|
|
21161
|
-
];
|
|
21162
|
-
};
|
|
21195
|
+
"type": "u32";
|
|
21163
21196
|
},
|
|
21164
21197
|
{
|
|
21165
21198
|
"name": "marketStats";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"address": "vELoC1audYbSYVRXn1vPaV8Axoa9oU6BYmNGZZBDZ1P",
|
|
3
3
|
"metadata": {
|
|
4
4
|
"name": "velocity",
|
|
5
|
-
"version": "2.163.
|
|
5
|
+
"version": "2.163.1",
|
|
6
6
|
"spec": "0.1.0",
|
|
7
7
|
"description": "Created with Anchor"
|
|
8
8
|
},
|
|
@@ -9672,6 +9672,38 @@
|
|
|
9672
9672
|
}
|
|
9673
9673
|
]
|
|
9674
9674
|
},
|
|
9675
|
+
{
|
|
9676
|
+
"name": "update_perp_market_bankruptcy_if_floor_pct",
|
|
9677
|
+
"discriminator": [
|
|
9678
|
+
192,
|
|
9679
|
+
2,
|
|
9680
|
+
229,
|
|
9681
|
+
220,
|
|
9682
|
+
243,
|
|
9683
|
+
115,
|
|
9684
|
+
121,
|
|
9685
|
+
84
|
|
9686
|
+
],
|
|
9687
|
+
"accounts": [
|
|
9688
|
+
{
|
|
9689
|
+
"name": "admin",
|
|
9690
|
+
"signer": true
|
|
9691
|
+
},
|
|
9692
|
+
{
|
|
9693
|
+
"name": "state"
|
|
9694
|
+
},
|
|
9695
|
+
{
|
|
9696
|
+
"name": "perp_market",
|
|
9697
|
+
"writable": true
|
|
9698
|
+
}
|
|
9699
|
+
],
|
|
9700
|
+
"args": [
|
|
9701
|
+
{
|
|
9702
|
+
"name": "bankruptcy_if_floor_pct",
|
|
9703
|
+
"type": "u32"
|
|
9704
|
+
}
|
|
9705
|
+
]
|
|
9706
|
+
},
|
|
9675
9707
|
{
|
|
9676
9708
|
"name": "update_perp_market_base_spread",
|
|
9677
9709
|
"discriminator": [
|
|
@@ -21140,20 +21172,21 @@
|
|
|
21140
21172
|
"type": "i8"
|
|
21141
21173
|
},
|
|
21142
21174
|
{
|
|
21143
|
-
"name": "
|
|
21175
|
+
"name": "bankruptcy_if_floor_pct",
|
|
21144
21176
|
"docs": [
|
|
21145
|
-
"
|
|
21146
|
-
"
|
|
21147
|
-
"
|
|
21148
|
-
"
|
|
21149
|
-
"
|
|
21177
|
+
"Floor on the unswept IF-fee carveout, as a percentage of open-interest",
|
|
21178
|
+
"notional (PERCENTAGE_PRECISION; 0 disables). The fee sweep's IF drain",
|
|
21179
|
+
"leaves `pending_if_fee` at (at least) this floor, so a standing",
|
|
21180
|
+
"first-loss tranche is always available to `resolve_perp_bankruptcy` —",
|
|
21181
|
+
"a permissionless sweep (or the inline sweep on any pnl settle) cannot",
|
|
21182
|
+
"drain the tranche below it ahead of a bankruptcy resolution. Notional",
|
|
21183
|
+
"is valued at the market's own oracle TWAP so a manipulated spot print",
|
|
21184
|
+
"can't crush the floor. Occupies the former 4-byte trailing padding",
|
|
21185
|
+
"before `market_stats` (same offset/alignment on all targets), so",
|
|
21186
|
+
"existing accounts read 0 = disabled until the admin sets it;",
|
|
21187
|
+
"new markets initialize to `DEFAULT_BANKRUPTCY_IF_FLOOR_PCT`."
|
|
21150
21188
|
],
|
|
21151
|
-
"type":
|
|
21152
|
-
"array": [
|
|
21153
|
-
"u8",
|
|
21154
|
-
4
|
|
21155
|
-
]
|
|
21156
|
-
}
|
|
21189
|
+
"type": "u32"
|
|
21157
21190
|
},
|
|
21158
21191
|
{
|
|
21159
21192
|
"name": "market_stats",
|
|
@@ -29,7 +29,7 @@ export declare function calculatePegFromTargetPrice(targetPrice: BN, baseAssetRe
|
|
|
29
29
|
* available to spend, QUOTE_PRECISION (1e6); `checkLowerBound` tells the caller whether it
|
|
30
30
|
* must still verify the repeg doesn't push `totalFeeMinusDistributions` negative.
|
|
31
31
|
*/
|
|
32
|
-
export declare function calculateOptimalPegAndBudget(amm: AMM, mmOraclePriceData: MMOraclePriceData): [BN, BN, BN, boolean];
|
|
32
|
+
export declare function calculateOptimalPegAndBudget(amm: AMM, mmOraclePriceData: Pick<MMOraclePriceData, 'price'>): [BN, BN, BN, boolean];
|
|
33
33
|
/**
|
|
34
34
|
* Determines the full curve update (repeg cost, K scale factor, new peg) for `amm` against
|
|
35
35
|
* the current oracle price, mirroring the "use full budget peg" fallback path of `adjust_amm`
|
|
@@ -46,7 +46,7 @@ export declare function calculateOptimalPegAndBudget(amm: AMM, mmOraclePriceData
|
|
|
46
46
|
* `calculateUpdatedAMM` whether it must still verify affordability against
|
|
47
47
|
* `totalFeeMinusDistributions`.
|
|
48
48
|
*/
|
|
49
|
-
export declare function calculateNewAmm(amm: AMM, mmOraclePriceData: MMOraclePriceData): [BN, BN, BN, BN, boolean];
|
|
49
|
+
export declare function calculateNewAmm(amm: AMM, mmOraclePriceData: Pick<MMOraclePriceData, 'price'>): [BN, BN, BN, BN, boolean];
|
|
50
50
|
/**
|
|
51
51
|
* Returns a copy of `amm` with its curve (peg, reserves, sqrtK) repegged/updated to the
|
|
52
52
|
* current oracle price, or `amm` unchanged if no update applies. Mirrors the program's
|
|
@@ -63,7 +63,7 @@ export declare function calculateNewAmm(amm: AMM, mmOraclePriceData: MMOraclePri
|
|
|
63
63
|
* @param mmOraclePriceData Current MM oracle price data; omit to skip the update entirely.
|
|
64
64
|
* @returns Updated `AMM` (new object), or the original `amm` reference if no update applies or the affordability gate rejects it.
|
|
65
65
|
*/
|
|
66
|
-
export declare function calculateUpdatedAMM(amm: AMM, mmOraclePriceData?: MMOraclePriceData): AMM;
|
|
66
|
+
export declare function calculateUpdatedAMM(amm: AMM, mmOraclePriceData?: Pick<MMOraclePriceData, 'price'>): AMM;
|
|
67
67
|
/**
|
|
68
68
|
* Repegs `amm` to the current oracle price (`calculateUpdatedAMM`) and returns the
|
|
69
69
|
* one-sided spread reserves (bid reserves for `short`, ask reserves for `long`) plus the
|
|
@@ -76,7 +76,7 @@ export declare function calculateUpdatedAMM(amm: AMM, mmOraclePriceData?: MMOrac
|
|
|
76
76
|
* @param latestSlot Current slot, forwarded for reference-price-offset smoothing.
|
|
77
77
|
* @returns `baseAssetReserve`/`quoteAssetReserve` for the requested side (AMM_RESERVE_PRECISION, 1e9), and the post-update `sqrtK`/`newPeg` (AMM_RESERVE_PRECISION 1e9 / PEG_PRECISION 1e6).
|
|
78
78
|
*/
|
|
79
|
-
export declare function calculateUpdatedAMMSpreadReserves(amm: AMM, marketStats: MarketStats, direction: PositionDirection, mmOraclePriceData?: MMOraclePriceData, latestSlot?: BN): {
|
|
79
|
+
export declare function calculateUpdatedAMMSpreadReserves(amm: AMM, marketStats: MarketStats, direction: PositionDirection, mmOraclePriceData?: Pick<MMOraclePriceData, 'price' | 'confidence'>, latestSlot?: BN): {
|
|
80
80
|
baseAssetReserve: BN;
|
|
81
81
|
quoteAssetReserve: BN;
|
|
82
82
|
sqrtK: BN;
|
|
@@ -92,7 +92,7 @@ export declare function calculateUpdatedAMMSpreadReserves(amm: AMM, marketStats:
|
|
|
92
92
|
* @param latestSlot Current slot, forwarded for reference-price-offset smoothing.
|
|
93
93
|
* @returns `[bidPrice, askPrice]`, both PRICE_PRECISION (1e6).
|
|
94
94
|
*/
|
|
95
|
-
export declare function calculateBidAskPrice(amm: AMM, marketStats: MarketStats, mmOraclePriceData?: MMOraclePriceData, withUpdate?: boolean, latestSlot?: BN): [BN, BN];
|
|
95
|
+
export declare function calculateBidAskPrice(amm: AMM, marketStats: MarketStats, mmOraclePriceData?: Pick<MMOraclePriceData, 'price' | 'confidence'>, withUpdate?: boolean, latestSlot?: BN): [BN, BN];
|
|
96
96
|
/**
|
|
97
97
|
* Computes the constant-product price implied by a pair of AMM reserves and a peg multiplier:
|
|
98
98
|
* `quoteAssetReserves * pegMultiplier / baseAssetReserves`, converted to `PRICE_PRECISION`.
|
|
@@ -338,7 +338,7 @@ export declare function calculateSpreadBN(baseSpread: number, lastOracleReserveP
|
|
|
338
338
|
* @throws if `oraclePriceData` is omitted while `baseSpread` and `curveUpdateIntensity` are both nonzero.
|
|
339
339
|
* @returns `[longSpread, shortSpread]`, both BID_ASK_SPREAD_PRECISION (1e6) fraction-of-price units.
|
|
340
340
|
*/
|
|
341
|
-
export declare function calculateSpread(amm: AMM, marketStats: MarketStats, oraclePriceData?: OraclePriceData, now?: BN, reservePrice?: BN): [number, number];
|
|
341
|
+
export declare function calculateSpread(amm: AMM, marketStats: MarketStats, oraclePriceData?: Pick<OraclePriceData, 'price' | 'confidence'>, now?: BN, reservePrice?: BN): [number, number];
|
|
342
342
|
/**
|
|
343
343
|
* Computes the AMM's one-sided bid and ask reserves — the reserves a long (ask side) or short
|
|
344
344
|
* (bid side) trade would actually execute against — by combining `calculateSpread`'s
|
|
@@ -357,7 +357,7 @@ export declare function calculateSpread(amm: AMM, marketStats: MarketStats, orac
|
|
|
357
357
|
* @param latestSlot Current slot; required for reference-price-offset smoothing to take effect (treated as 0 slots elapsed if omitted).
|
|
358
358
|
* @returns `[bidReserves, askReserves]`, each `{ baseAssetReserve, quoteAssetReserve }` in AMM_RESERVE_PRECISION (1e9).
|
|
359
359
|
*/
|
|
360
|
-
export declare function calculateSpreadReserves(amm: AMM, marketStats: MarketStats, mmOraclePriceData?: MMOraclePriceData, now?: BN, latestSlot?: BN): {
|
|
360
|
+
export declare function calculateSpreadReserves(amm: AMM, marketStats: MarketStats, mmOraclePriceData?: Pick<MMOraclePriceData, 'price' | 'confidence'>, now?: BN, latestSlot?: BN): {
|
|
361
361
|
baseAssetReserve: BN;
|
|
362
362
|
quoteAssetReserve: BN;
|
|
363
363
|
}[];
|
|
@@ -407,7 +407,7 @@ export declare function calculateTerminalPrice(market: PerpMarketAccount): BN;
|
|
|
407
407
|
* @param now Current unix timestamp (seconds), forwarded to `calculateSpreadReserves`.
|
|
408
408
|
* @returns `[baseAssetAmount, direction]`: `baseAssetAmount` is AMM_RESERVE_PRECISION (1e9), zero if the trade size would round to nothing.
|
|
409
409
|
*/
|
|
410
|
-
export declare function calculateMaxBaseAssetAmountToTrade(amm: AMM, marketStats: MarketStats, limit_price: BN, direction: PositionDirection, mmOraclePriceData: MMOraclePriceData, now?: BN): [BN, PositionDirection];
|
|
410
|
+
export declare function calculateMaxBaseAssetAmountToTrade(amm: AMM, marketStats: MarketStats, limit_price: BN, direction: PositionDirection, mmOraclePriceData: Pick<MMOraclePriceData, 'price' | 'confidence'>, now?: BN): [BN, PositionDirection];
|
|
411
411
|
/**
|
|
412
412
|
* Converts a quote-asset AMM reserve amount into the actual quote asset amount swapped
|
|
413
413
|
* (applying the peg multiplier), rounding by 1 in the direction that favors the AMM when
|
|
@@ -26,7 +26,7 @@ import { MMOraclePriceData, OraclePriceData } from '../oracles/types';
|
|
|
26
26
|
* straight-line interpolation; `lowerboundEst` further scales the spread down by the
|
|
27
27
|
* fraction of the current funding period that has elapsed since the last update.
|
|
28
28
|
*/
|
|
29
|
-
export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, mmOraclePriceData?: MMOraclePriceData, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): [BN, BN, BN, BN, BN];
|
|
29
|
+
export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, mmOraclePriceData?: Pick<MMOraclePriceData, 'price' | 'confidence'>, oraclePriceData?: Pick<OraclePriceData, 'price'>, markPrice?: BN, now?: BN): [BN, BN, BN, BN, BN];
|
|
30
30
|
/**
|
|
31
31
|
* Calculates estimated funding rates in human-readable form (plain JS `number` percentages,
|
|
32
32
|
* not BN), including a plain-English summary sentence. Values pass through floating-point
|
|
@@ -68,7 +68,7 @@ export declare function calculateLongShortFundingRate(market: PerpMarketAccount,
|
|
|
68
68
|
* @param now Current unix timestamp (seconds); defaults to wall-clock time.
|
|
69
69
|
* @returns `[markTwapLive, oracleTwapLive, longFundingRateEst, shortFundingRateEst]` — TWAPs in PRICE_PRECISION (1e6), rate estimates in the same scale as `calculateAllEstimatedFundingRate`.
|
|
70
70
|
*/
|
|
71
|
-
export declare function calculateLongShortFundingRateAndLiveTwaps(market: PerpMarketAccount, mmOraclePriceData?: MMOraclePriceData, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): [BN, BN, BN, BN];
|
|
71
|
+
export declare function calculateLongShortFundingRateAndLiveTwaps(market: PerpMarketAccount, mmOraclePriceData?: MMOraclePriceData, oraclePriceData?: Pick<OraclePriceData, 'price'>, markPrice?: BN, now?: BN): [BN, BN, BN, BN];
|
|
72
72
|
/**
|
|
73
73
|
* Estimated quote pool available to top up the smaller side's funding payment shortfall:
|
|
74
74
|
* one-third of the AMM's own retained equity (`totalFeeMinusDistributions`), floored at
|
|
@@ -141,10 +141,11 @@ export declare function calculateNetUserPnlImbalance(perpMarket: PerpMarketAccou
|
|
|
141
141
|
/**
|
|
142
142
|
* Calculates the price used to evaluate trigger (stop/take-profit) orders for a perp market,
|
|
143
143
|
* mirroring the Rust `get_trigger_price`. When `useMedianPrice` is true, the trigger price is the
|
|
144
|
-
* median of three candidates — the last fill price (or oracle price if there's been no fill
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* oracle price (tier A/B: 20bps,
|
|
144
|
+
* median of three candidates — the last fill price (or oracle price if there's been no fill or the
|
|
145
|
+
* last fill is older than `TRIGGER_PRICE_LAST_FILL_MAX_AGE`), the oracle price adjusted by the
|
|
146
|
+
* implied funding basis, and the oracle price adjusted by the 5min mark/oracle TWAP basis — then
|
|
147
|
+
* clamped to within a contract-tier-dependent band around the raw oracle price (tier A/B: 20bps,
|
|
148
|
+
* tier C: 100bps, others: 250bps) via `clampTriggerPrice`. This
|
|
148
149
|
* resists a single manipulated print (last fill or a momentary oracle/mark divergence) from
|
|
149
150
|
* triggering orders it shouldn't. When `useMedianPrice` is false, the raw oracle price is used
|
|
150
151
|
* directly with no smoothing.
|
|
@@ -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
|