perk-protocol 0.1.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/dist/client.d.ts +110 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +690 -0
- package/dist/client.js.map +1 -0
- package/dist/constants.d.ts +59 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +71 -0
- package/dist/constants.js.map +1 -0
- package/dist/cranker.d.ts +71 -0
- package/dist/cranker.d.ts.map +1 -0
- package/dist/cranker.js +441 -0
- package/dist/cranker.js.map +1 -0
- package/dist/idl.json +3740 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/dist/math.d.ts +60 -0
- package/dist/math.d.ts.map +1 -0
- package/dist/math.js +330 -0
- package/dist/math.js.map +1 -0
- package/dist/oracle-cranker.d.ts +72 -0
- package/dist/oracle-cranker.d.ts.map +1 -0
- package/dist/oracle-cranker.js +434 -0
- package/dist/oracle-cranker.js.map +1 -0
- package/dist/pda.d.ts +15 -0
- package/dist/pda.d.ts.map +1 -0
- package/dist/pda.js +45 -0
- package/dist/pda.js.map +1 -0
- package/dist/types.d.ts +252 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/package.json +36 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { PerkClient } from "./client";
|
|
2
|
+
export type { PerkClientConfig } from "./client";
|
|
3
|
+
export { PerkCranker } from "./cranker";
|
|
4
|
+
export type { CrankerConfig, CrankerMetrics } from "./cranker";
|
|
5
|
+
export { PerkOracleCranker } from "./oracle-cranker";
|
|
6
|
+
export type { OracleCrankerConfig, OracleCrankerMetrics } from "./oracle-cranker";
|
|
7
|
+
export { findProtocolAddress, findMarketAddress, findPositionAddress, findVaultAddress, findTriggerOrderAddress, findPerkOracleAddress, } from "./pda";
|
|
8
|
+
export { calculateMarkPrice, estimateExecutionPrice, calculateSlippageBps, effectivePositionQ, calculateNotional, initialMarginBps, marginRatio, isLiquidatable, estimateLiquidationPrice, calculateFee, fundingRateAnnualized, warmupProgress, haircutRatio, priceToNumber, numberToPrice, amountToNumber, accountEquity, calculateNotionalBN, isAboveMaintenanceMargin, } from "./math";
|
|
9
|
+
export { PERK_PROGRAM_ID, PROTOCOL_SEED, MARKET_SEED, POSITION_SEED, VAULT_SEED, TRIGGER_SEED, MIN_LEVERAGE, MAX_LEVERAGE, LEVERAGE_SCALE, MIN_TRADING_FEE_BPS, MAX_TRADING_FEE_BPS, DEFAULT_TRADING_FEE_BPS, LIQUIDATION_FEE_BPS, MAINTENANCE_MARGIN_BPS, CREATOR_FEE_SHARE_BPS, PRICE_SCALE, POS_SCALE, ADL_ONE, K_SCALE, MIN_INITIAL_K, DEFAULT_MARKET_CREATION_FEE, FUNDING_RATE_PRECISION, MAX_FUNDING_ITERATIONS, FUNDING_RATE_CAP_BPS, PEG_UPDATE_COOLDOWN_SLOTS, AMM_PEG_THRESHOLD_BPS, ORACLE_STALENESS_SECONDS, INSURANCE_EPOCH_SECONDS, INSURANCE_EPOCH_CAP_BPS, WARMUP_PERIOD_SLOTS, MAX_TRIGGER_ORDERS, BPS_DENOMINATOR, PERK_ORACLE_SEED, MIN_ORACLE_STALENESS_SECONDS, MAX_ORACLE_STALENESS_SECONDS, MAX_MIN_SOURCES, MAX_ORACLE_PRICE, MIN_PRICE_CHANGE_BPS, MAX_PRICE_CHANGE_BPS, MIN_CIRCUIT_BREAKER_BPS, MAX_CIRCUIT_BREAKER_BPS, CIRCUIT_BREAKER_WINDOW_SLOTS, WINDOW_BAND_MULTIPLIER, PYTH_PROGRAM_ID, PYTH_SOL_USD_FEED, MAX_FUNDING_DT, MIN_REMAINING_POSITION_SIZE, MIN_RECLAIM_DELAY_SLOTS, DUST_THRESHOLD, MIN_NONZERO_MM_REQ, MIN_NONZERO_IM_REQ, LIQUIDATOR_SHARE_BPS, TRIGGER_EXECUTION_FEE_BPS, MIN_DEPOSIT_AMOUNT, MIN_A_SIDE, MAX_TRIGGER_ORDER_AGE_SECONDS, } from "./constants";
|
|
10
|
+
export { Side, OracleSource, SideState, TriggerOrderType, } from "./types";
|
|
11
|
+
export type { ProtocolAccount, MarketAccount, UserPositionAccount, TriggerOrderAccount, PerkOracleAccount, CreateMarketParams, AdminUpdateMarketParams, TriggerOrderParams, InitPerkOracleParams, UpdatePerkOracleParams, UpdateOracleConfigParams, SetFallbackOracleParams, PositionInfo, MarketInfo, } from "./types";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAElF,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,eAAe,EACf,aAAa,EACb,WAAW,EACX,aAAa,EACb,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,OAAO,EACP,OAAO,EACP,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,EAC5B,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,EAC5B,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,2BAA2B,EAC3B,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,UAAU,EACV,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,YAAY,EACZ,UAAU,GACX,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @perk/sdk — TypeScript SDK for the Perk perpetual futures protocol on Solana
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.FUNDING_RATE_PRECISION = exports.DEFAULT_MARKET_CREATION_FEE = exports.MIN_INITIAL_K = exports.K_SCALE = exports.ADL_ONE = exports.POS_SCALE = exports.PRICE_SCALE = exports.CREATOR_FEE_SHARE_BPS = exports.MAINTENANCE_MARGIN_BPS = exports.LIQUIDATION_FEE_BPS = exports.DEFAULT_TRADING_FEE_BPS = exports.MAX_TRADING_FEE_BPS = exports.MIN_TRADING_FEE_BPS = exports.LEVERAGE_SCALE = exports.MAX_LEVERAGE = exports.MIN_LEVERAGE = exports.TRIGGER_SEED = exports.VAULT_SEED = exports.POSITION_SEED = exports.MARKET_SEED = exports.PROTOCOL_SEED = exports.PERK_PROGRAM_ID = exports.isAboveMaintenanceMargin = exports.calculateNotionalBN = exports.accountEquity = exports.amountToNumber = exports.numberToPrice = exports.priceToNumber = exports.haircutRatio = exports.warmupProgress = exports.fundingRateAnnualized = exports.calculateFee = exports.estimateLiquidationPrice = exports.isLiquidatable = exports.marginRatio = exports.initialMarginBps = exports.calculateNotional = exports.effectivePositionQ = exports.calculateSlippageBps = exports.estimateExecutionPrice = exports.calculateMarkPrice = exports.findPerkOracleAddress = exports.findTriggerOrderAddress = exports.findVaultAddress = exports.findPositionAddress = exports.findMarketAddress = exports.findProtocolAddress = exports.PerkOracleCranker = exports.PerkCranker = exports.PerkClient = void 0;
|
|
5
|
+
exports.TriggerOrderType = exports.SideState = exports.OracleSource = exports.Side = exports.MAX_TRIGGER_ORDER_AGE_SECONDS = exports.MIN_A_SIDE = exports.MIN_DEPOSIT_AMOUNT = exports.TRIGGER_EXECUTION_FEE_BPS = exports.LIQUIDATOR_SHARE_BPS = exports.MIN_NONZERO_IM_REQ = exports.MIN_NONZERO_MM_REQ = exports.DUST_THRESHOLD = exports.MIN_RECLAIM_DELAY_SLOTS = exports.MIN_REMAINING_POSITION_SIZE = exports.MAX_FUNDING_DT = exports.PYTH_SOL_USD_FEED = exports.PYTH_PROGRAM_ID = exports.WINDOW_BAND_MULTIPLIER = exports.CIRCUIT_BREAKER_WINDOW_SLOTS = exports.MAX_CIRCUIT_BREAKER_BPS = exports.MIN_CIRCUIT_BREAKER_BPS = exports.MAX_PRICE_CHANGE_BPS = exports.MIN_PRICE_CHANGE_BPS = exports.MAX_ORACLE_PRICE = exports.MAX_MIN_SOURCES = exports.MAX_ORACLE_STALENESS_SECONDS = exports.MIN_ORACLE_STALENESS_SECONDS = exports.PERK_ORACLE_SEED = exports.BPS_DENOMINATOR = exports.MAX_TRIGGER_ORDERS = exports.WARMUP_PERIOD_SLOTS = exports.INSURANCE_EPOCH_CAP_BPS = exports.INSURANCE_EPOCH_SECONDS = exports.ORACLE_STALENESS_SECONDS = exports.AMM_PEG_THRESHOLD_BPS = exports.PEG_UPDATE_COOLDOWN_SLOTS = exports.FUNDING_RATE_CAP_BPS = exports.MAX_FUNDING_ITERATIONS = void 0;
|
|
6
|
+
var client_1 = require("./client");
|
|
7
|
+
Object.defineProperty(exports, "PerkClient", { enumerable: true, get: function () { return client_1.PerkClient; } });
|
|
8
|
+
var cranker_1 = require("./cranker");
|
|
9
|
+
Object.defineProperty(exports, "PerkCranker", { enumerable: true, get: function () { return cranker_1.PerkCranker; } });
|
|
10
|
+
var oracle_cranker_1 = require("./oracle-cranker");
|
|
11
|
+
Object.defineProperty(exports, "PerkOracleCranker", { enumerable: true, get: function () { return oracle_cranker_1.PerkOracleCranker; } });
|
|
12
|
+
var pda_1 = require("./pda");
|
|
13
|
+
Object.defineProperty(exports, "findProtocolAddress", { enumerable: true, get: function () { return pda_1.findProtocolAddress; } });
|
|
14
|
+
Object.defineProperty(exports, "findMarketAddress", { enumerable: true, get: function () { return pda_1.findMarketAddress; } });
|
|
15
|
+
Object.defineProperty(exports, "findPositionAddress", { enumerable: true, get: function () { return pda_1.findPositionAddress; } });
|
|
16
|
+
Object.defineProperty(exports, "findVaultAddress", { enumerable: true, get: function () { return pda_1.findVaultAddress; } });
|
|
17
|
+
Object.defineProperty(exports, "findTriggerOrderAddress", { enumerable: true, get: function () { return pda_1.findTriggerOrderAddress; } });
|
|
18
|
+
Object.defineProperty(exports, "findPerkOracleAddress", { enumerable: true, get: function () { return pda_1.findPerkOracleAddress; } });
|
|
19
|
+
var math_1 = require("./math");
|
|
20
|
+
Object.defineProperty(exports, "calculateMarkPrice", { enumerable: true, get: function () { return math_1.calculateMarkPrice; } });
|
|
21
|
+
Object.defineProperty(exports, "estimateExecutionPrice", { enumerable: true, get: function () { return math_1.estimateExecutionPrice; } });
|
|
22
|
+
Object.defineProperty(exports, "calculateSlippageBps", { enumerable: true, get: function () { return math_1.calculateSlippageBps; } });
|
|
23
|
+
Object.defineProperty(exports, "effectivePositionQ", { enumerable: true, get: function () { return math_1.effectivePositionQ; } });
|
|
24
|
+
Object.defineProperty(exports, "calculateNotional", { enumerable: true, get: function () { return math_1.calculateNotional; } });
|
|
25
|
+
Object.defineProperty(exports, "initialMarginBps", { enumerable: true, get: function () { return math_1.initialMarginBps; } });
|
|
26
|
+
Object.defineProperty(exports, "marginRatio", { enumerable: true, get: function () { return math_1.marginRatio; } });
|
|
27
|
+
Object.defineProperty(exports, "isLiquidatable", { enumerable: true, get: function () { return math_1.isLiquidatable; } });
|
|
28
|
+
Object.defineProperty(exports, "estimateLiquidationPrice", { enumerable: true, get: function () { return math_1.estimateLiquidationPrice; } });
|
|
29
|
+
Object.defineProperty(exports, "calculateFee", { enumerable: true, get: function () { return math_1.calculateFee; } });
|
|
30
|
+
Object.defineProperty(exports, "fundingRateAnnualized", { enumerable: true, get: function () { return math_1.fundingRateAnnualized; } });
|
|
31
|
+
Object.defineProperty(exports, "warmupProgress", { enumerable: true, get: function () { return math_1.warmupProgress; } });
|
|
32
|
+
Object.defineProperty(exports, "haircutRatio", { enumerable: true, get: function () { return math_1.haircutRatio; } });
|
|
33
|
+
Object.defineProperty(exports, "priceToNumber", { enumerable: true, get: function () { return math_1.priceToNumber; } });
|
|
34
|
+
Object.defineProperty(exports, "numberToPrice", { enumerable: true, get: function () { return math_1.numberToPrice; } });
|
|
35
|
+
Object.defineProperty(exports, "amountToNumber", { enumerable: true, get: function () { return math_1.amountToNumber; } });
|
|
36
|
+
Object.defineProperty(exports, "accountEquity", { enumerable: true, get: function () { return math_1.accountEquity; } });
|
|
37
|
+
Object.defineProperty(exports, "calculateNotionalBN", { enumerable: true, get: function () { return math_1.calculateNotionalBN; } });
|
|
38
|
+
Object.defineProperty(exports, "isAboveMaintenanceMargin", { enumerable: true, get: function () { return math_1.isAboveMaintenanceMargin; } });
|
|
39
|
+
var constants_1 = require("./constants");
|
|
40
|
+
Object.defineProperty(exports, "PERK_PROGRAM_ID", { enumerable: true, get: function () { return constants_1.PERK_PROGRAM_ID; } });
|
|
41
|
+
Object.defineProperty(exports, "PROTOCOL_SEED", { enumerable: true, get: function () { return constants_1.PROTOCOL_SEED; } });
|
|
42
|
+
Object.defineProperty(exports, "MARKET_SEED", { enumerable: true, get: function () { return constants_1.MARKET_SEED; } });
|
|
43
|
+
Object.defineProperty(exports, "POSITION_SEED", { enumerable: true, get: function () { return constants_1.POSITION_SEED; } });
|
|
44
|
+
Object.defineProperty(exports, "VAULT_SEED", { enumerable: true, get: function () { return constants_1.VAULT_SEED; } });
|
|
45
|
+
Object.defineProperty(exports, "TRIGGER_SEED", { enumerable: true, get: function () { return constants_1.TRIGGER_SEED; } });
|
|
46
|
+
Object.defineProperty(exports, "MIN_LEVERAGE", { enumerable: true, get: function () { return constants_1.MIN_LEVERAGE; } });
|
|
47
|
+
Object.defineProperty(exports, "MAX_LEVERAGE", { enumerable: true, get: function () { return constants_1.MAX_LEVERAGE; } });
|
|
48
|
+
Object.defineProperty(exports, "LEVERAGE_SCALE", { enumerable: true, get: function () { return constants_1.LEVERAGE_SCALE; } });
|
|
49
|
+
Object.defineProperty(exports, "MIN_TRADING_FEE_BPS", { enumerable: true, get: function () { return constants_1.MIN_TRADING_FEE_BPS; } });
|
|
50
|
+
Object.defineProperty(exports, "MAX_TRADING_FEE_BPS", { enumerable: true, get: function () { return constants_1.MAX_TRADING_FEE_BPS; } });
|
|
51
|
+
Object.defineProperty(exports, "DEFAULT_TRADING_FEE_BPS", { enumerable: true, get: function () { return constants_1.DEFAULT_TRADING_FEE_BPS; } });
|
|
52
|
+
Object.defineProperty(exports, "LIQUIDATION_FEE_BPS", { enumerable: true, get: function () { return constants_1.LIQUIDATION_FEE_BPS; } });
|
|
53
|
+
Object.defineProperty(exports, "MAINTENANCE_MARGIN_BPS", { enumerable: true, get: function () { return constants_1.MAINTENANCE_MARGIN_BPS; } });
|
|
54
|
+
Object.defineProperty(exports, "CREATOR_FEE_SHARE_BPS", { enumerable: true, get: function () { return constants_1.CREATOR_FEE_SHARE_BPS; } });
|
|
55
|
+
Object.defineProperty(exports, "PRICE_SCALE", { enumerable: true, get: function () { return constants_1.PRICE_SCALE; } });
|
|
56
|
+
Object.defineProperty(exports, "POS_SCALE", { enumerable: true, get: function () { return constants_1.POS_SCALE; } });
|
|
57
|
+
Object.defineProperty(exports, "ADL_ONE", { enumerable: true, get: function () { return constants_1.ADL_ONE; } });
|
|
58
|
+
Object.defineProperty(exports, "K_SCALE", { enumerable: true, get: function () { return constants_1.K_SCALE; } });
|
|
59
|
+
Object.defineProperty(exports, "MIN_INITIAL_K", { enumerable: true, get: function () { return constants_1.MIN_INITIAL_K; } });
|
|
60
|
+
Object.defineProperty(exports, "DEFAULT_MARKET_CREATION_FEE", { enumerable: true, get: function () { return constants_1.DEFAULT_MARKET_CREATION_FEE; } });
|
|
61
|
+
Object.defineProperty(exports, "FUNDING_RATE_PRECISION", { enumerable: true, get: function () { return constants_1.FUNDING_RATE_PRECISION; } });
|
|
62
|
+
Object.defineProperty(exports, "MAX_FUNDING_ITERATIONS", { enumerable: true, get: function () { return constants_1.MAX_FUNDING_ITERATIONS; } });
|
|
63
|
+
Object.defineProperty(exports, "FUNDING_RATE_CAP_BPS", { enumerable: true, get: function () { return constants_1.FUNDING_RATE_CAP_BPS; } });
|
|
64
|
+
Object.defineProperty(exports, "PEG_UPDATE_COOLDOWN_SLOTS", { enumerable: true, get: function () { return constants_1.PEG_UPDATE_COOLDOWN_SLOTS; } });
|
|
65
|
+
Object.defineProperty(exports, "AMM_PEG_THRESHOLD_BPS", { enumerable: true, get: function () { return constants_1.AMM_PEG_THRESHOLD_BPS; } });
|
|
66
|
+
Object.defineProperty(exports, "ORACLE_STALENESS_SECONDS", { enumerable: true, get: function () { return constants_1.ORACLE_STALENESS_SECONDS; } });
|
|
67
|
+
Object.defineProperty(exports, "INSURANCE_EPOCH_SECONDS", { enumerable: true, get: function () { return constants_1.INSURANCE_EPOCH_SECONDS; } });
|
|
68
|
+
Object.defineProperty(exports, "INSURANCE_EPOCH_CAP_BPS", { enumerable: true, get: function () { return constants_1.INSURANCE_EPOCH_CAP_BPS; } });
|
|
69
|
+
Object.defineProperty(exports, "WARMUP_PERIOD_SLOTS", { enumerable: true, get: function () { return constants_1.WARMUP_PERIOD_SLOTS; } });
|
|
70
|
+
Object.defineProperty(exports, "MAX_TRIGGER_ORDERS", { enumerable: true, get: function () { return constants_1.MAX_TRIGGER_ORDERS; } });
|
|
71
|
+
Object.defineProperty(exports, "BPS_DENOMINATOR", { enumerable: true, get: function () { return constants_1.BPS_DENOMINATOR; } });
|
|
72
|
+
Object.defineProperty(exports, "PERK_ORACLE_SEED", { enumerable: true, get: function () { return constants_1.PERK_ORACLE_SEED; } });
|
|
73
|
+
Object.defineProperty(exports, "MIN_ORACLE_STALENESS_SECONDS", { enumerable: true, get: function () { return constants_1.MIN_ORACLE_STALENESS_SECONDS; } });
|
|
74
|
+
Object.defineProperty(exports, "MAX_ORACLE_STALENESS_SECONDS", { enumerable: true, get: function () { return constants_1.MAX_ORACLE_STALENESS_SECONDS; } });
|
|
75
|
+
Object.defineProperty(exports, "MAX_MIN_SOURCES", { enumerable: true, get: function () { return constants_1.MAX_MIN_SOURCES; } });
|
|
76
|
+
Object.defineProperty(exports, "MAX_ORACLE_PRICE", { enumerable: true, get: function () { return constants_1.MAX_ORACLE_PRICE; } });
|
|
77
|
+
Object.defineProperty(exports, "MIN_PRICE_CHANGE_BPS", { enumerable: true, get: function () { return constants_1.MIN_PRICE_CHANGE_BPS; } });
|
|
78
|
+
Object.defineProperty(exports, "MAX_PRICE_CHANGE_BPS", { enumerable: true, get: function () { return constants_1.MAX_PRICE_CHANGE_BPS; } });
|
|
79
|
+
Object.defineProperty(exports, "MIN_CIRCUIT_BREAKER_BPS", { enumerable: true, get: function () { return constants_1.MIN_CIRCUIT_BREAKER_BPS; } });
|
|
80
|
+
Object.defineProperty(exports, "MAX_CIRCUIT_BREAKER_BPS", { enumerable: true, get: function () { return constants_1.MAX_CIRCUIT_BREAKER_BPS; } });
|
|
81
|
+
Object.defineProperty(exports, "CIRCUIT_BREAKER_WINDOW_SLOTS", { enumerable: true, get: function () { return constants_1.CIRCUIT_BREAKER_WINDOW_SLOTS; } });
|
|
82
|
+
Object.defineProperty(exports, "WINDOW_BAND_MULTIPLIER", { enumerable: true, get: function () { return constants_1.WINDOW_BAND_MULTIPLIER; } });
|
|
83
|
+
Object.defineProperty(exports, "PYTH_PROGRAM_ID", { enumerable: true, get: function () { return constants_1.PYTH_PROGRAM_ID; } });
|
|
84
|
+
Object.defineProperty(exports, "PYTH_SOL_USD_FEED", { enumerable: true, get: function () { return constants_1.PYTH_SOL_USD_FEED; } });
|
|
85
|
+
Object.defineProperty(exports, "MAX_FUNDING_DT", { enumerable: true, get: function () { return constants_1.MAX_FUNDING_DT; } });
|
|
86
|
+
Object.defineProperty(exports, "MIN_REMAINING_POSITION_SIZE", { enumerable: true, get: function () { return constants_1.MIN_REMAINING_POSITION_SIZE; } });
|
|
87
|
+
Object.defineProperty(exports, "MIN_RECLAIM_DELAY_SLOTS", { enumerable: true, get: function () { return constants_1.MIN_RECLAIM_DELAY_SLOTS; } });
|
|
88
|
+
Object.defineProperty(exports, "DUST_THRESHOLD", { enumerable: true, get: function () { return constants_1.DUST_THRESHOLD; } });
|
|
89
|
+
Object.defineProperty(exports, "MIN_NONZERO_MM_REQ", { enumerable: true, get: function () { return constants_1.MIN_NONZERO_MM_REQ; } });
|
|
90
|
+
Object.defineProperty(exports, "MIN_NONZERO_IM_REQ", { enumerable: true, get: function () { return constants_1.MIN_NONZERO_IM_REQ; } });
|
|
91
|
+
Object.defineProperty(exports, "LIQUIDATOR_SHARE_BPS", { enumerable: true, get: function () { return constants_1.LIQUIDATOR_SHARE_BPS; } });
|
|
92
|
+
Object.defineProperty(exports, "TRIGGER_EXECUTION_FEE_BPS", { enumerable: true, get: function () { return constants_1.TRIGGER_EXECUTION_FEE_BPS; } });
|
|
93
|
+
Object.defineProperty(exports, "MIN_DEPOSIT_AMOUNT", { enumerable: true, get: function () { return constants_1.MIN_DEPOSIT_AMOUNT; } });
|
|
94
|
+
Object.defineProperty(exports, "MIN_A_SIDE", { enumerable: true, get: function () { return constants_1.MIN_A_SIDE; } });
|
|
95
|
+
Object.defineProperty(exports, "MAX_TRIGGER_ORDER_AGE_SECONDS", { enumerable: true, get: function () { return constants_1.MAX_TRIGGER_ORDER_AGE_SECONDS; } });
|
|
96
|
+
var types_1 = require("./types");
|
|
97
|
+
Object.defineProperty(exports, "Side", { enumerable: true, get: function () { return types_1.Side; } });
|
|
98
|
+
Object.defineProperty(exports, "OracleSource", { enumerable: true, get: function () { return types_1.OracleSource; } });
|
|
99
|
+
Object.defineProperty(exports, "SideState", { enumerable: true, get: function () { return types_1.SideState; } });
|
|
100
|
+
Object.defineProperty(exports, "TriggerOrderType", { enumerable: true, get: function () { return types_1.TriggerOrderType; } });
|
|
101
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,+EAA+E;;;;AAE/E,mCAAsC;AAA7B,oGAAA,UAAU,OAAA;AAGnB,qCAAwC;AAA/B,sGAAA,WAAW,OAAA;AAGpB,mDAAqD;AAA5C,mHAAA,iBAAiB,OAAA;AAG1B,6BAOe;AANb,0GAAA,mBAAmB,OAAA;AACnB,wGAAA,iBAAiB,OAAA;AACjB,0GAAA,mBAAmB,OAAA;AACnB,uGAAA,gBAAgB,OAAA;AAChB,8GAAA,uBAAuB,OAAA;AACvB,4GAAA,qBAAqB,OAAA;AAGvB,+BAoBgB;AAnBd,0GAAA,kBAAkB,OAAA;AAClB,8GAAA,sBAAsB,OAAA;AACtB,4GAAA,oBAAoB,OAAA;AACpB,0GAAA,kBAAkB,OAAA;AAClB,yGAAA,iBAAiB,OAAA;AACjB,wGAAA,gBAAgB,OAAA;AAChB,mGAAA,WAAW,OAAA;AACX,sGAAA,cAAc,OAAA;AACd,gHAAA,wBAAwB,OAAA;AACxB,oGAAA,YAAY,OAAA;AACZ,6GAAA,qBAAqB,OAAA;AACrB,sGAAA,cAAc,OAAA;AACd,oGAAA,YAAY,OAAA;AACZ,qGAAA,aAAa,OAAA;AACb,qGAAA,aAAa,OAAA;AACb,sGAAA,cAAc,OAAA;AACd,qGAAA,aAAa,OAAA;AACb,2GAAA,mBAAmB,OAAA;AACnB,gHAAA,wBAAwB,OAAA;AAG1B,yCAyDqB;AAxDnB,4GAAA,eAAe,OAAA;AACf,0GAAA,aAAa,OAAA;AACb,wGAAA,WAAW,OAAA;AACX,0GAAA,aAAa,OAAA;AACb,uGAAA,UAAU,OAAA;AACV,yGAAA,YAAY,OAAA;AACZ,yGAAA,YAAY,OAAA;AACZ,yGAAA,YAAY,OAAA;AACZ,2GAAA,cAAc,OAAA;AACd,gHAAA,mBAAmB,OAAA;AACnB,gHAAA,mBAAmB,OAAA;AACnB,oHAAA,uBAAuB,OAAA;AACvB,gHAAA,mBAAmB,OAAA;AACnB,mHAAA,sBAAsB,OAAA;AACtB,kHAAA,qBAAqB,OAAA;AACrB,wGAAA,WAAW,OAAA;AACX,sGAAA,SAAS,OAAA;AACT,oGAAA,OAAO,OAAA;AACP,oGAAA,OAAO,OAAA;AACP,0GAAA,aAAa,OAAA;AACb,wHAAA,2BAA2B,OAAA;AAC3B,mHAAA,sBAAsB,OAAA;AACtB,mHAAA,sBAAsB,OAAA;AACtB,iHAAA,oBAAoB,OAAA;AACpB,sHAAA,yBAAyB,OAAA;AACzB,kHAAA,qBAAqB,OAAA;AACrB,qHAAA,wBAAwB,OAAA;AACxB,oHAAA,uBAAuB,OAAA;AACvB,oHAAA,uBAAuB,OAAA;AACvB,gHAAA,mBAAmB,OAAA;AACnB,+GAAA,kBAAkB,OAAA;AAClB,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,yHAAA,4BAA4B,OAAA;AAC5B,yHAAA,4BAA4B,OAAA;AAC5B,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,iHAAA,oBAAoB,OAAA;AACpB,iHAAA,oBAAoB,OAAA;AACpB,oHAAA,uBAAuB,OAAA;AACvB,oHAAA,uBAAuB,OAAA;AACvB,yHAAA,4BAA4B,OAAA;AAC5B,mHAAA,sBAAsB,OAAA;AACtB,4GAAA,eAAe,OAAA;AACf,8GAAA,iBAAiB,OAAA;AACjB,2GAAA,cAAc,OAAA;AACd,wHAAA,2BAA2B,OAAA;AAC3B,oHAAA,uBAAuB,OAAA;AACvB,2GAAA,cAAc,OAAA;AACd,+GAAA,kBAAkB,OAAA;AAClB,+GAAA,kBAAkB,OAAA;AAClB,iHAAA,oBAAoB,OAAA;AACpB,sHAAA,yBAAyB,OAAA;AACzB,+GAAA,kBAAkB,OAAA;AAClB,uGAAA,UAAU,OAAA;AACV,0HAAA,6BAA6B,OAAA;AAG/B,iCAKiB;AAJf,6FAAA,IAAI,OAAA;AACJ,qGAAA,YAAY,OAAA;AACZ,kGAAA,SAAS,OAAA;AACT,yGAAA,gBAAgB,OAAA"}
|
package/dist/math.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import BN from "bn.js";
|
|
2
|
+
import { MarketAccount, UserPositionAccount, Side } from "./types";
|
|
3
|
+
/** Convert on-chain scaled price (u64, 6 decimals) to human-readable number. */
|
|
4
|
+
export declare function priceToNumber(price: BN): number;
|
|
5
|
+
/** Convert human-readable price to on-chain scaled price. */
|
|
6
|
+
export declare function numberToPrice(price: number): BN;
|
|
7
|
+
/** Convert on-chain token amount (with decimals) to human-readable. */
|
|
8
|
+
export declare function amountToNumber(amount: BN, decimals?: number): number;
|
|
9
|
+
/** Calculate the vAMM mark price (returns human-readable number). */
|
|
10
|
+
export declare function calculateMarkPrice(market: MarketAccount): number;
|
|
11
|
+
/** Estimate execution price for a trade (constant product, returns human-readable). */
|
|
12
|
+
export declare function estimateExecutionPrice(market: MarketAccount, side: Side, baseSize: BN): number;
|
|
13
|
+
/** Calculate slippage in BPS between execution price and mark price. */
|
|
14
|
+
export declare function calculateSlippageBps(executionPrice: number, markPrice: number): number;
|
|
15
|
+
/** Calculate effective position size (accounts for ADL A-coefficient + epoch). */
|
|
16
|
+
export declare function effectivePositionQ(position: UserPositionAccount, market: MarketAccount): BN;
|
|
17
|
+
/** Calculate notional value of a position (BN, raw on-chain units). */
|
|
18
|
+
export declare function calculateNotionalBN(position: UserPositionAccount, market: MarketAccount, oraclePrice: BN): BN;
|
|
19
|
+
/** Calculate notional value (human-readable number, for display).
|
|
20
|
+
* Uses BN precision internally; converts to JS Number at the end.
|
|
21
|
+
* Note: for notional > Number.MAX_SAFE_INTEGER (~9e15) precision degrades
|
|
22
|
+
* due to IEEE 754 limits. Use calculateNotionalBN for exact values. */
|
|
23
|
+
export declare function calculateNotional(position: UserPositionAccount, market: MarketAccount, oraclePrice: BN): number;
|
|
24
|
+
/** Compute account equity matching on-chain logic.
|
|
25
|
+
* equity = max(0, collateral + pnl - feeDebt) */
|
|
26
|
+
export declare function accountEquity(position: UserPositionAccount): BN;
|
|
27
|
+
/** Calculate initial margin requirement in BPS for a given leverage. */
|
|
28
|
+
export declare function initialMarginBps(maxLeverage: number): number;
|
|
29
|
+
/** Check if position is above maintenance margin (matches on-chain). */
|
|
30
|
+
export declare function isAboveMaintenanceMargin(position: UserPositionAccount, market: MarketAccount, oraclePrice: BN): boolean;
|
|
31
|
+
/** Check if position is liquidatable. */
|
|
32
|
+
export declare function isLiquidatable(position: UserPositionAccount, market: MarketAccount, oraclePrice: BN): boolean;
|
|
33
|
+
/** Calculate margin ratio for a position (for display). */
|
|
34
|
+
export declare function marginRatio(position: UserPositionAccount, market: MarketAccount, oraclePrice: BN): number;
|
|
35
|
+
/** Estimate liquidation price for a position (human-readable, e.g. 150.0 for $150).
|
|
36
|
+
*
|
|
37
|
+
* Uses closed-form solution derived from on-chain K-diff PnL model:
|
|
38
|
+
* pnl_delta(P) = |basis| * A_mult * (P - P_last) / (a_basis * POS_SCALE)
|
|
39
|
+
* notional(P) = |effQ| * P / POS_SCALE
|
|
40
|
+
*
|
|
41
|
+
* Liquidation occurs when equity <= mm_requirement:
|
|
42
|
+
* equity_now + pnl_delta(P) = |effQ| * P * mmBps / (POS_SCALE * 10000)
|
|
43
|
+
*
|
|
44
|
+
* Both sides are linear in P → solve directly. O(1), no binary search.
|
|
45
|
+
*
|
|
46
|
+
* Approximation: ignores funding accrual between now and liquidation
|
|
47
|
+
* (funding is time-dependent, not price-dependent). For UI display. */
|
|
48
|
+
export declare function estimateLiquidationPrice(position: UserPositionAccount, market: MarketAccount, oraclePrice: BN): number | null;
|
|
49
|
+
/** Calculate trading fee for a given notional. */
|
|
50
|
+
export declare function calculateFee(notional: number, feeBps: number): number;
|
|
51
|
+
/** Calculate funding rate (annualized %). */
|
|
52
|
+
export declare function fundingRateAnnualized(market: MarketAccount): number;
|
|
53
|
+
/** Calculate warmup progress (0 to 1).
|
|
54
|
+
* Matches on-chain slope-based model: slope = max(1, R / period).
|
|
55
|
+
* Release cap = slope * elapsed; progress = min(cap, R) / R. */
|
|
56
|
+
export declare function warmupProgress(position: UserPositionAccount, market: MarketAccount, currentSlot: BN): number;
|
|
57
|
+
/** Calculate haircut ratio (what fraction of matured PnL is withdrawable).
|
|
58
|
+
* Matches on-chain risk::haircut_ratio() — computed dynamically from market state. */
|
|
59
|
+
export declare function haircutRatio(market: MarketAccount): number;
|
|
60
|
+
//# sourceMappingURL=math.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,OAAO,CAAC;AASvB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAUnE,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,KAAK,EAAE,EAAE,GAAG,MAAM,CAE/C;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,EAAE,CAE/C;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAE,MAAU,GAAG,MAAM,CAEvE;AAID,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAWhE;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,EAAE,GACX,MAAM,CAyBR;AAED,wEAAwE;AACxE,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,MAAM,CAGR;AASD,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,GACpB,EAAE,CAkBJ;AAED,uEAAuE;AACvE,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,EAAE,CAKJ;AAED;;;wEAGwE;AACxE,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,MAAM,CAMR;AAED;kDACkD;AAClD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,EAAE,CAc/D;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,OAAO,CAeT;AAED,yCAAyC;AACzC,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,OAAO,CAIT;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CACzB,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,MAAM,CAKR;AAED;;;;;;;;;;;;wEAYwE;AACxE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,MAAM,GAAG,IAAI,CAmEf;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,6CAA6C;AAC7C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAKnE;AAED;;iEAEiE;AACjE,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,EAAE,GACd,MAAM,CAsBR;AAED;uFACuF;AACvF,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAuB1D"}
|
package/dist/math.js
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.priceToNumber = priceToNumber;
|
|
7
|
+
exports.numberToPrice = numberToPrice;
|
|
8
|
+
exports.amountToNumber = amountToNumber;
|
|
9
|
+
exports.calculateMarkPrice = calculateMarkPrice;
|
|
10
|
+
exports.estimateExecutionPrice = estimateExecutionPrice;
|
|
11
|
+
exports.calculateSlippageBps = calculateSlippageBps;
|
|
12
|
+
exports.effectivePositionQ = effectivePositionQ;
|
|
13
|
+
exports.calculateNotionalBN = calculateNotionalBN;
|
|
14
|
+
exports.calculateNotional = calculateNotional;
|
|
15
|
+
exports.accountEquity = accountEquity;
|
|
16
|
+
exports.initialMarginBps = initialMarginBps;
|
|
17
|
+
exports.isAboveMaintenanceMargin = isAboveMaintenanceMargin;
|
|
18
|
+
exports.isLiquidatable = isLiquidatable;
|
|
19
|
+
exports.marginRatio = marginRatio;
|
|
20
|
+
exports.estimateLiquidationPrice = estimateLiquidationPrice;
|
|
21
|
+
exports.calculateFee = calculateFee;
|
|
22
|
+
exports.fundingRateAnnualized = fundingRateAnnualized;
|
|
23
|
+
exports.warmupProgress = warmupProgress;
|
|
24
|
+
exports.haircutRatio = haircutRatio;
|
|
25
|
+
const bn_js_1 = __importDefault(require("bn.js"));
|
|
26
|
+
const constants_1 = require("./constants");
|
|
27
|
+
const types_1 = require("./types");
|
|
28
|
+
const ZERO = new bn_js_1.default(0);
|
|
29
|
+
const BN_PRICE_SCALE = new bn_js_1.default(constants_1.PRICE_SCALE);
|
|
30
|
+
const BN_POS_SCALE = new bn_js_1.default(constants_1.POS_SCALE);
|
|
31
|
+
const BN_BPS_DENOM = new bn_js_1.default(constants_1.BPS_DENOMINATOR);
|
|
32
|
+
const MIN_NONZERO_MM_REQ = new bn_js_1.default(10000);
|
|
33
|
+
// ── Price Helpers ──
|
|
34
|
+
/** Convert on-chain scaled price (u64, 6 decimals) to human-readable number. */
|
|
35
|
+
function priceToNumber(price) {
|
|
36
|
+
return price.toNumber() / constants_1.PRICE_SCALE;
|
|
37
|
+
}
|
|
38
|
+
/** Convert human-readable price to on-chain scaled price. */
|
|
39
|
+
function numberToPrice(price) {
|
|
40
|
+
return new bn_js_1.default(Math.round(price * constants_1.PRICE_SCALE));
|
|
41
|
+
}
|
|
42
|
+
/** Convert on-chain token amount (with decimals) to human-readable. */
|
|
43
|
+
function amountToNumber(amount, decimals = 9) {
|
|
44
|
+
return amount.toNumber() / Math.pow(10, decimals);
|
|
45
|
+
}
|
|
46
|
+
// ── vAMM Math ──
|
|
47
|
+
/** Calculate the vAMM mark price (returns human-readable number). */
|
|
48
|
+
function calculateMarkPrice(market) {
|
|
49
|
+
if (market.baseReserve.isZero())
|
|
50
|
+
return 0;
|
|
51
|
+
// mark = quote_reserve * peg_multiplier / (base_reserve * PRICE_SCALE)
|
|
52
|
+
// Use BN arithmetic to avoid u128 overflow, convert to number at the end
|
|
53
|
+
const numerator = market.quoteReserve.mul(market.pegMultiplier);
|
|
54
|
+
const denominator = market.baseReserve.mul(BN_PRICE_SCALE);
|
|
55
|
+
// Result is a ratio close to 1.0 for balanced reserves, safe to convert
|
|
56
|
+
// Use high-precision: multiply numerator by 1e12 first, divide, then divide by 1e12
|
|
57
|
+
const PRECISION = new bn_js_1.default("1000000000000");
|
|
58
|
+
const scaled = numerator.mul(PRECISION).div(denominator);
|
|
59
|
+
return scaled.toNumber() / 1e12;
|
|
60
|
+
}
|
|
61
|
+
/** Estimate execution price for a trade (constant product, returns human-readable). */
|
|
62
|
+
function estimateExecutionPrice(market, side, baseSize) {
|
|
63
|
+
const base = market.baseReserve;
|
|
64
|
+
const quote = market.quoteReserve;
|
|
65
|
+
const peg = market.pegMultiplier;
|
|
66
|
+
const k = market.k; // Use stored k, not recomputed (avoids rounding drift)
|
|
67
|
+
if (side === types_1.Side.Long) {
|
|
68
|
+
const newBase = base.sub(baseSize);
|
|
69
|
+
if (newBase.isZero() || newBase.isNeg())
|
|
70
|
+
return Infinity;
|
|
71
|
+
const newQuote = k.div(newBase);
|
|
72
|
+
const quoteDelta = newQuote.sub(quote);
|
|
73
|
+
// exec_price = quoteDelta * peg / (size * PRICE_SCALE)
|
|
74
|
+
const PRECISION = new bn_js_1.default("1000000000000");
|
|
75
|
+
const num = quoteDelta.mul(peg).mul(PRECISION);
|
|
76
|
+
const den = baseSize.mul(BN_PRICE_SCALE);
|
|
77
|
+
return num.div(den).toNumber() / 1e12;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const newBase = base.add(baseSize);
|
|
81
|
+
const newQuote = k.div(newBase);
|
|
82
|
+
const quoteDelta = quote.sub(newQuote);
|
|
83
|
+
const PRECISION = new bn_js_1.default("1000000000000");
|
|
84
|
+
const num = quoteDelta.mul(peg).mul(PRECISION);
|
|
85
|
+
const den = baseSize.mul(BN_PRICE_SCALE);
|
|
86
|
+
return num.div(den).toNumber() / 1e12;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Calculate slippage in BPS between execution price and mark price. */
|
|
90
|
+
function calculateSlippageBps(executionPrice, markPrice) {
|
|
91
|
+
if (markPrice === 0)
|
|
92
|
+
return 0;
|
|
93
|
+
return Math.abs(((executionPrice - markPrice) / markPrice) * constants_1.BPS_DENOMINATOR);
|
|
94
|
+
}
|
|
95
|
+
// ── Position Math ──
|
|
96
|
+
/** Get the epoch for a side from the market. */
|
|
97
|
+
function getEpochSide(market, isLong) {
|
|
98
|
+
return isLong ? market.longEpoch : market.shortEpoch;
|
|
99
|
+
}
|
|
100
|
+
/** Calculate effective position size (accounts for ADL A-coefficient + epoch). */
|
|
101
|
+
function effectivePositionQ(position, market) {
|
|
102
|
+
const basis = position.basis;
|
|
103
|
+
if (basis.isZero())
|
|
104
|
+
return ZERO;
|
|
105
|
+
const isLong = !basis.isNeg();
|
|
106
|
+
const absBasis = basis.abs();
|
|
107
|
+
const aSide = isLong ? market.longA : market.shortA;
|
|
108
|
+
const aBasis = position.aSnapshot;
|
|
109
|
+
// Epoch mismatch check — position was wiped by ADL reset
|
|
110
|
+
const epochSide = getEpochSide(market, isLong);
|
|
111
|
+
if (!position.epochSnapshot.eq(epochSide))
|
|
112
|
+
return ZERO;
|
|
113
|
+
if (aBasis.isZero())
|
|
114
|
+
return ZERO;
|
|
115
|
+
// floor(|basis| * a_side / a_basis)
|
|
116
|
+
const result = absBasis.mul(aSide).div(aBasis);
|
|
117
|
+
return basis.isNeg() ? result.neg() : result;
|
|
118
|
+
}
|
|
119
|
+
/** Calculate notional value of a position (BN, raw on-chain units). */
|
|
120
|
+
function calculateNotionalBN(position, market, oraclePrice) {
|
|
121
|
+
const effQ = effectivePositionQ(position, market);
|
|
122
|
+
if (effQ.isZero())
|
|
123
|
+
return ZERO;
|
|
124
|
+
// notional = |eff| * price / POS_SCALE
|
|
125
|
+
return effQ.abs().mul(oraclePrice).div(BN_POS_SCALE);
|
|
126
|
+
}
|
|
127
|
+
/** Calculate notional value (human-readable number, for display).
|
|
128
|
+
* Uses BN precision internally; converts to JS Number at the end.
|
|
129
|
+
* Note: for notional > Number.MAX_SAFE_INTEGER (~9e15) precision degrades
|
|
130
|
+
* due to IEEE 754 limits. Use calculateNotionalBN for exact values. */
|
|
131
|
+
function calculateNotional(position, market, oraclePrice) {
|
|
132
|
+
const notional = calculateNotionalBN(position, market, oraclePrice);
|
|
133
|
+
// For values within safe integer range, convert directly (lossless)
|
|
134
|
+
if (notional.bitLength() <= 53)
|
|
135
|
+
return notional.toNumber();
|
|
136
|
+
// For large values, go through string to avoid intermediate overflow
|
|
137
|
+
return parseFloat(notional.toString());
|
|
138
|
+
}
|
|
139
|
+
/** Compute account equity matching on-chain logic.
|
|
140
|
+
* equity = max(0, collateral + pnl - feeDebt) */
|
|
141
|
+
function accountEquity(position) {
|
|
142
|
+
const collateral = position.depositedCollateral;
|
|
143
|
+
const pnl = position.pnl; // i128 (can be negative)
|
|
144
|
+
const feeCredits = position.feeCredits; // i128 (negative = debt)
|
|
145
|
+
// fee_debt = abs(min(0, feeCredits))
|
|
146
|
+
const feeDebt = feeCredits.isNeg() ? feeCredits.abs() : ZERO;
|
|
147
|
+
// equity_raw = collateral + pnl - feeDebt
|
|
148
|
+
let equityRaw = new bn_js_1.default(collateral.toString()).add(pnl).sub(feeDebt);
|
|
149
|
+
// Clamp to 0 (matches on-chain max(0, eq_raw))
|
|
150
|
+
if (equityRaw.isNeg())
|
|
151
|
+
equityRaw = ZERO;
|
|
152
|
+
return equityRaw;
|
|
153
|
+
}
|
|
154
|
+
/** Calculate initial margin requirement in BPS for a given leverage. */
|
|
155
|
+
function initialMarginBps(maxLeverage) {
|
|
156
|
+
const leverageActual = Math.floor(maxLeverage / constants_1.LEVERAGE_SCALE);
|
|
157
|
+
if (leverageActual <= 0)
|
|
158
|
+
return constants_1.BPS_DENOMINATOR;
|
|
159
|
+
const raw = Math.floor(constants_1.BPS_DENOMINATOR / leverageActual);
|
|
160
|
+
return Math.max(raw, constants_1.MAINTENANCE_MARGIN_BPS + 1);
|
|
161
|
+
}
|
|
162
|
+
/** Check if position is above maintenance margin (matches on-chain). */
|
|
163
|
+
function isAboveMaintenanceMargin(position, market, oraclePrice) {
|
|
164
|
+
const equity = accountEquity(position);
|
|
165
|
+
const notional = calculateNotionalBN(position, market, oraclePrice);
|
|
166
|
+
// mm_req = notional * market.maintenanceMarginBps / 10000
|
|
167
|
+
const mmBps = new bn_js_1.default(market.maintenanceMarginBps);
|
|
168
|
+
let mmReq = notional.mul(mmBps).div(BN_BPS_DENOM);
|
|
169
|
+
// Apply MIN_NONZERO_MM_REQ floor for non-zero positions
|
|
170
|
+
if (!notional.isZero()) {
|
|
171
|
+
mmReq = bn_js_1.default.max(mmReq, MIN_NONZERO_MM_REQ);
|
|
172
|
+
}
|
|
173
|
+
// On-chain: eq_net > mm_req (strictly greater)
|
|
174
|
+
return equity.gt(mmReq);
|
|
175
|
+
}
|
|
176
|
+
/** Check if position is liquidatable. */
|
|
177
|
+
function isLiquidatable(position, market, oraclePrice) {
|
|
178
|
+
const effQ = effectivePositionQ(position, market);
|
|
179
|
+
if (effQ.isZero() && position.baseSize.isZero())
|
|
180
|
+
return false;
|
|
181
|
+
return !isAboveMaintenanceMargin(position, market, oraclePrice);
|
|
182
|
+
}
|
|
183
|
+
/** Calculate margin ratio for a position (for display). */
|
|
184
|
+
function marginRatio(position, market, oraclePrice) {
|
|
185
|
+
const notional = calculateNotional(position, market, oraclePrice);
|
|
186
|
+
if (notional === 0)
|
|
187
|
+
return Infinity;
|
|
188
|
+
const equity = accountEquity(position);
|
|
189
|
+
return equity.toNumber() / notional;
|
|
190
|
+
}
|
|
191
|
+
/** Estimate liquidation price for a position (human-readable, e.g. 150.0 for $150).
|
|
192
|
+
*
|
|
193
|
+
* Uses closed-form solution derived from on-chain K-diff PnL model:
|
|
194
|
+
* pnl_delta(P) = |basis| * A_mult * (P - P_last) / (a_basis * POS_SCALE)
|
|
195
|
+
* notional(P) = |effQ| * P / POS_SCALE
|
|
196
|
+
*
|
|
197
|
+
* Liquidation occurs when equity <= mm_requirement:
|
|
198
|
+
* equity_now + pnl_delta(P) = |effQ| * P * mmBps / (POS_SCALE * 10000)
|
|
199
|
+
*
|
|
200
|
+
* Both sides are linear in P → solve directly. O(1), no binary search.
|
|
201
|
+
*
|
|
202
|
+
* Approximation: ignores funding accrual between now and liquidation
|
|
203
|
+
* (funding is time-dependent, not price-dependent). For UI display. */
|
|
204
|
+
function estimateLiquidationPrice(position, market, oraclePrice) {
|
|
205
|
+
const effQ = effectivePositionQ(position, market);
|
|
206
|
+
if (effQ.isZero())
|
|
207
|
+
return null;
|
|
208
|
+
const isLong = !effQ.isNeg();
|
|
209
|
+
const currentPriceHuman = oraclePrice.toNumber() / constants_1.PRICE_SCALE;
|
|
210
|
+
// Already liquidatable
|
|
211
|
+
if (isLiquidatable(position, market, oraclePrice)) {
|
|
212
|
+
return currentPriceHuman;
|
|
213
|
+
}
|
|
214
|
+
// Current equity (scalar, can use .toNumber() — equity is clamped to u64 range)
|
|
215
|
+
const equity = accountEquity(position);
|
|
216
|
+
const equityNum = equity.toNumber();
|
|
217
|
+
// PnL sensitivity to price: how much PnL changes per unit of scaled price.
|
|
218
|
+
// On-chain: pnl_delta = |basis| * A_mult * delta_P / (a_basis * POS_SCALE)
|
|
219
|
+
// where A_mult = longA or shortA (the market-level ADL multiplier).
|
|
220
|
+
//
|
|
221
|
+
// The position's a_basis (aSnapshot) was set to A_mult at position open,
|
|
222
|
+
// so |basis| * A_mult / a_basis = |effQ| (the effective position size).
|
|
223
|
+
// This means: pnl_delta = |effQ| * delta_P / POS_SCALE
|
|
224
|
+
//
|
|
225
|
+
// In human price units (dividing scaled price by PRICE_SCALE):
|
|
226
|
+
// pnl_per_unit = |effQ| * PRICE_SCALE / POS_SCALE
|
|
227
|
+
const absEffQ = effQ.abs().toNumber();
|
|
228
|
+
const pnlPerUnit = absEffQ * constants_1.PRICE_SCALE / constants_1.POS_SCALE;
|
|
229
|
+
// MM requirement per unit price:
|
|
230
|
+
// mm_per_unit = |effQ| * mmBps / (POS_SCALE * 10000)
|
|
231
|
+
// In human price units: mm_per_unit_human = |effQ| * PRICE_SCALE * mmBps / (POS_SCALE * 10000)
|
|
232
|
+
const mmBps = market.maintenanceMarginBps;
|
|
233
|
+
const mmPerUnit = absEffQ * constants_1.PRICE_SCALE * mmBps / (constants_1.POS_SCALE * constants_1.BPS_DENOMINATOR);
|
|
234
|
+
// Solve: equity + sign * pnlPerUnit * (P - currentPrice) = mmPerUnit * P
|
|
235
|
+
// where sign = +1 for longs (price up = profit), -1 for shorts (price down = profit)
|
|
236
|
+
//
|
|
237
|
+
// For longs: equity + pnlPerUnit * P - pnlPerUnit * currentPrice = mmPerUnit * P
|
|
238
|
+
// equity - pnlPerUnit * currentPrice = P * (mmPerUnit - pnlPerUnit)
|
|
239
|
+
// P = (equity - pnlPerUnit * currentPrice) / (mmPerUnit - pnlPerUnit)
|
|
240
|
+
//
|
|
241
|
+
// For shorts: equity - pnlPerUnit * P + pnlPerUnit * currentPrice = mmPerUnit * P
|
|
242
|
+
// equity + pnlPerUnit * currentPrice = P * (mmPerUnit + pnlPerUnit)
|
|
243
|
+
// P = (equity + pnlPerUnit * currentPrice) / (mmPerUnit + pnlPerUnit)
|
|
244
|
+
let liqPrice;
|
|
245
|
+
if (isLong) {
|
|
246
|
+
const denominator = mmPerUnit - pnlPerUnit;
|
|
247
|
+
// If denominator >= 0, longs can't be liquidated (MM requirement grows
|
|
248
|
+
// slower than equity — position is always solvent as price rises)
|
|
249
|
+
if (denominator >= 0)
|
|
250
|
+
return null;
|
|
251
|
+
liqPrice = (equityNum - pnlPerUnit * currentPriceHuman) / denominator;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
const denominator = mmPerUnit + pnlPerUnit;
|
|
255
|
+
if (denominator <= 0)
|
|
256
|
+
return null; // Can't happen for valid positions
|
|
257
|
+
liqPrice = (equityNum + pnlPerUnit * currentPriceHuman) / denominator;
|
|
258
|
+
}
|
|
259
|
+
// Sanity: price must be positive
|
|
260
|
+
if (liqPrice <= 0)
|
|
261
|
+
return null;
|
|
262
|
+
// Sanity: longs liquidate below current price, shorts above
|
|
263
|
+
if (isLong && liqPrice >= currentPriceHuman)
|
|
264
|
+
return currentPriceHuman;
|
|
265
|
+
if (!isLong && liqPrice <= currentPriceHuman)
|
|
266
|
+
return currentPriceHuman;
|
|
267
|
+
return liqPrice;
|
|
268
|
+
}
|
|
269
|
+
/** Calculate trading fee for a given notional. */
|
|
270
|
+
function calculateFee(notional, feeBps) {
|
|
271
|
+
return Math.ceil((notional * feeBps) / constants_1.BPS_DENOMINATOR);
|
|
272
|
+
}
|
|
273
|
+
/** Calculate funding rate (annualized %). */
|
|
274
|
+
function fundingRateAnnualized(market) {
|
|
275
|
+
const ratePerSlot = market.fundingRateBpsPerSlotLast.toNumber();
|
|
276
|
+
// ~2.5 slots per second on Solana
|
|
277
|
+
const slotsPerYear = 2.5 * 86400 * 365;
|
|
278
|
+
return (ratePerSlot * slotsPerYear) / (constants_1.FUNDING_RATE_PRECISION * 100);
|
|
279
|
+
}
|
|
280
|
+
/** Calculate warmup progress (0 to 1).
|
|
281
|
+
* Matches on-chain slope-based model: slope = max(1, R / period).
|
|
282
|
+
* Release cap = slope * elapsed; progress = min(cap, R) / R. */
|
|
283
|
+
function warmupProgress(position, market, currentSlot) {
|
|
284
|
+
if (position.reservedPnl.isZero())
|
|
285
|
+
return 1;
|
|
286
|
+
const period = market.warmupPeriodSlots;
|
|
287
|
+
if (period.isZero())
|
|
288
|
+
return 1;
|
|
289
|
+
// On-chain: slope = max(1, reserved_pnl / warmup_period_slots)
|
|
290
|
+
// The position stores warmupSlope set at warmup start.
|
|
291
|
+
const slope = position.warmupSlope.isZero()
|
|
292
|
+
? bn_js_1.default.max(new bn_js_1.default(1), position.reservedPnl.div(period))
|
|
293
|
+
: position.warmupSlope;
|
|
294
|
+
const elapsed = currentSlot.sub(position.warmupStartedAtSlot);
|
|
295
|
+
if (elapsed.isNeg())
|
|
296
|
+
return 0;
|
|
297
|
+
// cap = slope * elapsed (saturating)
|
|
298
|
+
const cap = slope.mul(elapsed);
|
|
299
|
+
// released = min(reserved_pnl, cap)
|
|
300
|
+
const released = bn_js_1.default.min(position.reservedPnl, cap);
|
|
301
|
+
// Progress = released / reserved_pnl
|
|
302
|
+
if (position.reservedPnl.isZero())
|
|
303
|
+
return 1;
|
|
304
|
+
return released.toNumber() / position.reservedPnl.toNumber();
|
|
305
|
+
}
|
|
306
|
+
/** Calculate haircut ratio (what fraction of matured PnL is withdrawable).
|
|
307
|
+
* Matches on-chain risk::haircut_ratio() — computed dynamically from market state. */
|
|
308
|
+
function haircutRatio(market) {
|
|
309
|
+
// If no matured positive PnL, ratio is 1 (no haircut needed)
|
|
310
|
+
if (market.pnlMaturedPosTot.isZero())
|
|
311
|
+
return 1;
|
|
312
|
+
// Senior claims: c_tot + insurance + claimable fees
|
|
313
|
+
const claimable = market.creatorClaimableFees.add(market.protocolClaimableFees);
|
|
314
|
+
const seniorSum = market.cTot
|
|
315
|
+
.add(new bn_js_1.default(market.insuranceFundBalance.toString()))
|
|
316
|
+
.add(claimable);
|
|
317
|
+
// Residual = vault_balance - senior_claims (clamped to 0)
|
|
318
|
+
const vaultBal = new bn_js_1.default(market.vaultBalance.toString());
|
|
319
|
+
const residual = vaultBal.gt(seniorSum) ? vaultBal.sub(seniorSum) : ZERO;
|
|
320
|
+
// h = min(residual, pnl_matured_pos_tot) / pnl_matured_pos_tot
|
|
321
|
+
const hNum = bn_js_1.default.min(residual, market.pnlMaturedPosTot);
|
|
322
|
+
const hDen = market.pnlMaturedPosTot;
|
|
323
|
+
if (hDen.isZero())
|
|
324
|
+
return 1;
|
|
325
|
+
// Use BN precision to avoid .toNumber() overflow on large pnl_matured_pos_tot
|
|
326
|
+
const RATIO_PRECISION = new bn_js_1.default("1000000000000"); // 1e12
|
|
327
|
+
const scaled = hNum.mul(RATIO_PRECISION).div(hDen);
|
|
328
|
+
return scaled.toNumber() / 1e12;
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=math.js.map
|
package/dist/math.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"math.js","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { Wallet } from "@coral-xyz/anchor";
|
|
3
|
+
export interface OracleCrankerConfig {
|
|
4
|
+
connection: Connection;
|
|
5
|
+
wallet: Wallet;
|
|
6
|
+
/** Token mints to post prices for. */
|
|
7
|
+
tokenMints: PublicKey[];
|
|
8
|
+
/** Update interval in ms (default: 3000 — ~every 7-8 slots). */
|
|
9
|
+
updateIntervalMs?: number;
|
|
10
|
+
/** Birdeye API key (optional — if not provided, skip Birdeye source). */
|
|
11
|
+
birdeyeApiKey?: string;
|
|
12
|
+
/** Priority fee in microlamports per CU (default: 50000). */
|
|
13
|
+
priorityFeeMicroLamports?: number;
|
|
14
|
+
/** Max deviation between sources before rejecting an outlier (default: 0.01 = 1%).
|
|
15
|
+
* Must be ≤ half of on-chain ORACLE_CONFIDENCE_BPS (2%) because confidence = max-min,
|
|
16
|
+
* so two sources at ±X% produce 2X% confidence. 1% deviation → max 2% confidence → passes. */
|
|
17
|
+
maxSourceDeviationPct?: number;
|
|
18
|
+
/** Minimum number of valid sources required (should match on-chain min_sources).
|
|
19
|
+
* Default: 1 (since Raydium is stubbed, requiring 2 would deadlock when one API is down). */
|
|
20
|
+
minSources?: number;
|
|
21
|
+
/** HTTP fetch timeout in ms (default: 5000). Prevents hung connections from freezing the cranker. */
|
|
22
|
+
fetchTimeoutMs?: number;
|
|
23
|
+
/** Jito bundle configuration. If provided, oracle updates are submitted as private Jito bundles
|
|
24
|
+
* to prevent front-running / MEV extraction on oracle price updates. */
|
|
25
|
+
jito?: {
|
|
26
|
+
/** Jito Block Engine URL (default: mainnet). */
|
|
27
|
+
blockEngineUrl?: string;
|
|
28
|
+
/** Tip in lamports to include in the bundle (default: 10000 = 0.00001 SOL). */
|
|
29
|
+
tipLamports?: number;
|
|
30
|
+
/** If true, do NOT fall back to normal RPC when Jito fails. Prevents mempool leakage
|
|
31
|
+
* at the cost of missed updates when Jito is down. Default: false. */
|
|
32
|
+
jitoOnly?: boolean;
|
|
33
|
+
};
|
|
34
|
+
/** Callback for logging. */
|
|
35
|
+
onLog?: (msg: string) => void;
|
|
36
|
+
/** Callback for errors. */
|
|
37
|
+
onError?: (err: Error, context: string) => void;
|
|
38
|
+
/** Callback for metrics. */
|
|
39
|
+
onMetrics?: (metrics: OracleCrankerMetrics) => void;
|
|
40
|
+
}
|
|
41
|
+
export interface OracleCrankerMetrics {
|
|
42
|
+
tickDurationMs: number;
|
|
43
|
+
mintsProcessed: number;
|
|
44
|
+
updatesPosted: number;
|
|
45
|
+
sourcesFetched: number;
|
|
46
|
+
outlierRejections: number;
|
|
47
|
+
errors: number;
|
|
48
|
+
}
|
|
49
|
+
export declare class PerkOracleCranker {
|
|
50
|
+
private client;
|
|
51
|
+
private config;
|
|
52
|
+
private running;
|
|
53
|
+
private intervalId;
|
|
54
|
+
private tickInProgress;
|
|
55
|
+
constructor(config: OracleCrankerConfig);
|
|
56
|
+
/**
|
|
57
|
+
* Submit a transaction as a Jito bundle for private, front-run-resistant submission.
|
|
58
|
+
* Falls back to normal RPC submission if Jito fails.
|
|
59
|
+
*/
|
|
60
|
+
private sendViaJito;
|
|
61
|
+
private log;
|
|
62
|
+
private handleError;
|
|
63
|
+
/** Start the oracle cranker loop. */
|
|
64
|
+
start(): void;
|
|
65
|
+
/** Stop the oracle cranker loop gracefully. Waits for current tick to finish (up to timeoutMs, default 30s). */
|
|
66
|
+
stop(timeoutMs?: number): Promise<void>;
|
|
67
|
+
/** Returns true if the oracle cranker is currently running. */
|
|
68
|
+
isRunning(): boolean;
|
|
69
|
+
private tick;
|
|
70
|
+
private _tickInner;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=oracle-cranker.d.ts.map
|