@reyaxyz/common 0.373.1 → 0.374.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/README.md +1 -1
- package/dist/types/utils/realized-balance.d.ts +11 -0
- package/dist/types/utils/realized-balance.d.ts.map +1 -1
- package/dist/utils/realized-balance.js +41 -7
- package/dist/utils/realized-balance.js.map +1 -1
- package/package.json +2 -2
- package/src/utils/realized-balance.ts +55 -6
package/README.md
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
|
|
7
7
|
| Statements | Branches | Functions | Lines |
|
|
8
8
|
| --------------------------- | ----------------------- | ------------------------- | ----------------- |
|
|
9
|
-
|  |  |  |  |
|
|
10
10
|
|
|
@@ -43,6 +43,17 @@ export declare class SettlementTrackerError extends Error {
|
|
|
43
43
|
readonly reason: 'missing' | 'inconsistent';
|
|
44
44
|
constructor(marketId: string, reason: 'missing' | 'inconsistent');
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Market trackers older than the position's own snapshot carry nothing the
|
|
48
|
+
* stored position does not already reflect. Off-chain tracker feeds can lag
|
|
49
|
+
* the position stream.
|
|
50
|
+
*/
|
|
51
|
+
export declare function trackersBehindPosition(position: Pick<RealizedBalancePosition, 'block_number'>, trackers: Pick<RealizedBalanceTrackers, 'blockNumber'>): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The trackers to ADL-adjust a position's quantity with, guarded the way its
|
|
54
|
+
* settlement is: behind the position, its own multiplier and unwind price stand in.
|
|
55
|
+
*/
|
|
56
|
+
export declare function positionAdjustmentTrackers<T extends Pick<RealizedBalanceTrackers, 'longTrackersBaseMultiplier' | 'shortTrackersBaseMultiplier' | 'longTrackersAdlUnwindPrice' | 'shortTrackersAdlUnwindPrice' | 'blockNumber'>>(position: Pick<RealizedBalancePosition, 'block_number' | 'base_multiplier' | 'adl_unwind_price'>, trackers: T): T;
|
|
46
57
|
/** Mirrors perpOB updatePerpPosition, including PRBMath truncation at each step. */
|
|
47
58
|
export declare function calculateSettledPositionPnl(position: RealizedBalancePosition, trackers: RealizedBalanceTrackers | undefined, onGuarded?: () => void): BigNumber;
|
|
48
59
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realized-balance.d.ts","sourceRoot":"/","sources":["utils/realized-balance.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,cAAc,CAAC;AAErC,kEAAkE;AAClE,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,CAAC;IAClC,IAAI,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,aAAa,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,eAAe,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/C,gBAAgB,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAChD,UAAU,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1C,wFAAwF;IACxF,YAAY,CAAC,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC;IAClC,0BAA0B,EAAE,MAAM,CAAC;IACnC,2BAA2B,EAAE,MAAM,CAAC;IACpC,0BAA0B,EAAE,MAAM,CAAC;IACnC,2BAA2B,EAAE,MAAM,CAAC;IACpC,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,4EAA4E;AAC5E,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,SAAS,GAAG,cAAc;gBADlC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,GAAG,cAAc;CAWrD;
|
|
1
|
+
{"version":3,"file":"realized-balance.d.ts","sourceRoot":"/","sources":["utils/realized-balance.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,cAAc,CAAC;AAErC,kEAAkE;AAClE,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,CAAC;IAClC,IAAI,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,aAAa,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,eAAe,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/C,gBAAgB,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAChD,UAAU,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1C,wFAAwF;IACxF,YAAY,CAAC,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC;IAClC,0BAA0B,EAAE,MAAM,CAAC;IACnC,2BAA2B,EAAE,MAAM,CAAC;IACpC,0BAA0B,EAAE,MAAM,CAAC;IACnC,2BAA2B,EAAE,MAAM,CAAC;IACpC,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,4EAA4E;AAC5E,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,SAAS,GAAG,cAAc;gBADlC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,GAAG,cAAc;CAWrD;AAaD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,EAAE,cAAc,CAAC,EACvD,QAAQ,EAAE,IAAI,CAAC,uBAAuB,EAAE,aAAa,CAAC,GACrD,OAAO,CAIT;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,CAAC,SAAS,IAAI,CACZ,uBAAuB,EACrB,4BAA4B,GAC5B,6BAA6B,GAC7B,4BAA4B,GAC5B,6BAA6B,GAC7B,aAAa,CAChB,EAED,QAAQ,EAAE,IAAI,CACZ,uBAAuB,EACvB,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,CACxD,EACD,QAAQ,EAAE,CAAC,GACV,CAAC,CAgBH;AAOD,oFAAoF;AACpF,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,uBAAuB,EACjC,QAAQ,EAAE,uBAAuB,GAAG,SAAS,EAC7C,SAAS,CAAC,EAAE,MAAM,IAAI,GACrB,SAAS,CAuEX;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,uBAAuB,EAAE,EACpC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,EAC1D,kBAAkB,EAAE,MAAM,EAC1B,SAAS,CAAC,EAAE,MAAM,IAAI,GACrB,SAAS,CAaX"}
|
|
@@ -14,11 +14,22 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
14
14
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
15
|
};
|
|
16
16
|
})();
|
|
17
|
+
var __assign = (this && this.__assign) || function () {
|
|
18
|
+
__assign = Object.assign || function(t) {
|
|
19
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
+
s = arguments[i];
|
|
21
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
+
t[p] = s[p];
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
};
|
|
26
|
+
return __assign.apply(this, arguments);
|
|
27
|
+
};
|
|
17
28
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
29
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
30
|
};
|
|
20
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.calculateSettledAccountPnl = exports.calculateSettledPositionPnl = exports.SettlementTrackerError = void 0;
|
|
32
|
+
exports.calculateSettledAccountPnl = exports.calculateSettledPositionPnl = exports.positionAdjustmentTrackers = exports.trackersBehindPosition = exports.SettlementTrackerError = void 0;
|
|
22
33
|
var bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
23
34
|
/** Structured cause for service metrics; calculation still fails closed. */
|
|
24
35
|
var SettlementTrackerError = /** @class */ (function (_super) {
|
|
@@ -52,6 +63,31 @@ var optionalBlock = function (value) {
|
|
|
52
63
|
var result = new bignumber_js_1.default(value.toString());
|
|
53
64
|
return result.isInteger() ? result : undefined;
|
|
54
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Market trackers older than the position's own snapshot carry nothing the
|
|
68
|
+
* stored position does not already reflect. Off-chain tracker feeds can lag
|
|
69
|
+
* the position stream.
|
|
70
|
+
*/
|
|
71
|
+
function trackersBehindPosition(position, trackers) {
|
|
72
|
+
var positionBlock = optionalBlock(position.block_number);
|
|
73
|
+
var trackerBlock = optionalBlock(trackers.blockNumber);
|
|
74
|
+
return !!positionBlock && !!trackerBlock && positionBlock.gt(trackerBlock);
|
|
75
|
+
}
|
|
76
|
+
exports.trackersBehindPosition = trackersBehindPosition;
|
|
77
|
+
/**
|
|
78
|
+
* The trackers to ADL-adjust a position's quantity with, guarded the way its
|
|
79
|
+
* settlement is: behind the position, its own multiplier and unwind price stand in.
|
|
80
|
+
*/
|
|
81
|
+
function positionAdjustmentTrackers(position, trackers) {
|
|
82
|
+
if (!trackersBehindPosition(position, trackers) ||
|
|
83
|
+
position.base_multiplier === null ||
|
|
84
|
+
position.adl_unwind_price === null)
|
|
85
|
+
return trackers;
|
|
86
|
+
var multiplier = position.base_multiplier.toString();
|
|
87
|
+
var unwind = position.adl_unwind_price.toString();
|
|
88
|
+
return __assign(__assign({}, trackers), { longTrackersBaseMultiplier: multiplier, shortTrackersBaseMultiplier: multiplier, longTrackersAdlUnwindPrice: unwind, shortTrackersAdlUnwindPrice: unwind });
|
|
89
|
+
}
|
|
90
|
+
exports.positionAdjustmentTrackers = positionAdjustmentTrackers;
|
|
55
91
|
var mulWad = function (a, b) {
|
|
56
92
|
return a.times(b).dividedToIntegerBy(WAD);
|
|
57
93
|
};
|
|
@@ -85,12 +121,10 @@ function calculateSettledPositionPnl(position, trackers, onGuarded) {
|
|
|
85
121
|
return realized;
|
|
86
122
|
// Market trackers older than the position's own snapshot carry no new
|
|
87
123
|
// cashflow: the stored realized PnL already settled everything up to the
|
|
88
|
-
// position's block.
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
var trackerBlock = optionalBlock(trackers.blockNumber);
|
|
93
|
-
if (positionBlock && trackerBlock && positionBlock.gt(trackerBlock)) {
|
|
124
|
+
// position's block. Treat that window as "nothing accrued" instead of
|
|
125
|
+
// projecting a delta backwards (wrong-sign funding, or an ADL guard failure
|
|
126
|
+
// below).
|
|
127
|
+
if (trackersBehindPosition(position, trackers)) {
|
|
94
128
|
onGuarded === null || onGuarded === void 0 ? void 0 : onGuarded();
|
|
95
129
|
return realized;
|
|
96
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realized-balance.js","sourceRoot":"/","sources":["utils/realized-balance.ts"],"names":[],"mappings":"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","sourcesContent":["import BigNumber from 'bignumber.js';\n\n/** Raw E18 position values, from either Prisma or replication. */\nexport type RealizedBalancePosition = {\n market_id: { toString(): string };\n base: { toString(): string } | null;\n realized_pnl: { toString(): string } | null;\n funding_value: { toString(): string } | null;\n base_multiplier: { toString(): string } | null;\n adl_unwind_price: { toString(): string } | null;\n last_price: { toString(): string } | null;\n /** Block the stored trackers were written at; lets stale market trackers be ignored. */\n block_number?: { toString(): string } | null;\n};\n\nexport type RealizedBalanceTrackers = {\n longTrackersFundingValue: string;\n shortTrackersFundingValue: string;\n longTrackersBaseMultiplier: string;\n shortTrackersBaseMultiplier: string;\n longTrackersAdlUnwindPrice: string;\n shortTrackersAdlUnwindPrice: string;\n /** Block the market trackers were observed at (optional; enables the staleness guard). */\n blockNumber?: string | null;\n};\n\n/** Structured cause for service metrics; calculation still fails closed. */\nexport class SettlementTrackerError extends Error {\n constructor(\n public readonly marketId: string,\n public readonly reason: 'missing' | 'inconsistent',\n ) {\n super(\n reason === 'missing'\n ? `Missing market trackers for ${marketId}`\n : `Inconsistent ADL trackers for ${marketId}`,\n );\n // common targets ES5; restore Error subclass identity after downleveling.\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = 'SettlementTrackerError';\n }\n}\n\nconst WAD = new BigNumber('1000000000000000000');\nconst integer = (value: { toString(): string } | null, field: string) => {\n const result = new BigNumber(value?.toString() ?? NaN);\n if (!result.isInteger()) throw new Error(`Missing or invalid ${field}`);\n return result;\n};\nconst optionalBlock = (value: { toString(): string } | null | undefined) => {\n if (value === null || value === undefined) return undefined;\n const result = new BigNumber(value.toString());\n return result.isInteger() ? result : undefined;\n};\nconst mulWad = (a: BigNumber, b: BigNumber) =>\n a.times(b).dividedToIntegerBy(WAD);\nconst divWad = (a: BigNumber, b: BigNumber) =>\n a.times(WAD).dividedToIntegerBy(b);\n\n/** Mirrors perpOB updatePerpPosition, including PRBMath truncation at each step. */\nexport function calculateSettledPositionPnl(\n position: RealizedBalancePosition,\n trackers: RealizedBalanceTrackers | undefined,\n onGuarded?: () => void,\n): BigNumber {\n const base = integer(position.base, 'position base');\n const realized = integer(position.realized_pnl, 'realized PnL');\n if (base.isZero()) return realized;\n if (!trackers)\n throw new SettlementTrackerError(position.market_id.toString(), 'missing');\n\n const long = base.isPositive();\n const funding = integer(\n long\n ? trackers.longTrackersFundingValue\n : trackers.shortTrackersFundingValue,\n 'market funding',\n );\n const multiplier = integer(\n long\n ? trackers.longTrackersBaseMultiplier\n : trackers.shortTrackersBaseMultiplier,\n 'market multiplier',\n );\n const unwind = integer(\n long\n ? trackers.longTrackersAdlUnwindPrice\n : trackers.shortTrackersAdlUnwindPrice,\n 'market unwind price',\n );\n const oldMultiplier = integer(\n position.base_multiplier,\n 'position multiplier',\n );\n const oldUnwind = integer(position.adl_unwind_price, 'position unwind price');\n const oldFunding = integer(position.funding_value, 'position funding');\n if (\n funding.eq(oldFunding) &&\n multiplier.eq(oldMultiplier) &&\n unwind.eq(oldUnwind)\n )\n return realized;\n\n // Market trackers older than the position's own snapshot carry no new\n // cashflow: the stored realized PnL already settled everything up to the\n // position's block. Off-chain tracker feeds can lag the position stream, so\n // treat that window as \"nothing accrued\" instead of projecting a delta\n // backwards (wrong-sign funding, or an ADL guard failure below).\n const positionBlock = optionalBlock(position.block_number);\n const trackerBlock = optionalBlock(trackers.blockNumber);\n if (positionBlock && trackerBlock && positionBlock.gt(trackerBlock)) {\n onGuarded?.();\n return realized;\n }\n\n if (\n oldMultiplier.lte(0) ||\n multiplier.lt(0) ||\n multiplier.gt(oldMultiplier) ||\n unwind.lt(oldUnwind)\n ) {\n throw new SettlementTrackerError(\n position.market_id.toString(),\n 'inconsistent',\n );\n }\n const fundingCashflow = mulWad(\n divWad(funding.minus(oldFunding), oldMultiplier),\n base.negated(),\n );\n const unwindDelta = divWad(unwind.minus(oldUnwind), oldMultiplier);\n const initialPrice = mulWad(\n WAD.minus(divWad(multiplier, oldMultiplier)),\n integer(position.last_price, 'position price'),\n );\n const adlCashflow = mulWad(base, unwindDelta.minus(initialPrice));\n return realized.plus(fundingCashflow).plus(adlCashflow);\n}\n\n/**\n * Returns raw E18 PnL aligned to collateral units. The instrument floors EACH\n * market's PnL to quote-token precision before Core aggregates collateral info.\n * Funding is the stored market tracker delta; do not extrapolate it with time.\n */\nexport function calculateSettledAccountPnl(\n positions: RealizedBalancePosition[],\n trackers: Partial<Record<string, RealizedBalanceTrackers>>,\n collateralDecimals: number,\n onGuarded?: () => void,\n): BigNumber {\n return positions.reduce((sum, position) => {\n const pnl = calculateSettledPositionPnl(\n position,\n trackers[position.market_id.toString()],\n onGuarded,\n );\n const rounded = pnl\n .shiftedBy(collateralDecimals - 18)\n .integerValue(BigNumber.ROUND_FLOOR)\n .shiftedBy(18 - collateralDecimals);\n return sum.plus(rounded);\n }, new BigNumber(0));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"realized-balance.js","sourceRoot":"/","sources":["utils/realized-balance.ts"],"names":[],"mappings":"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","sourcesContent":["import BigNumber from 'bignumber.js';\n\n/** Raw E18 position values, from either Prisma or replication. */\nexport type RealizedBalancePosition = {\n market_id: { toString(): string };\n base: { toString(): string } | null;\n realized_pnl: { toString(): string } | null;\n funding_value: { toString(): string } | null;\n base_multiplier: { toString(): string } | null;\n adl_unwind_price: { toString(): string } | null;\n last_price: { toString(): string } | null;\n /** Block the stored trackers were written at; lets stale market trackers be ignored. */\n block_number?: { toString(): string } | null;\n};\n\nexport type RealizedBalanceTrackers = {\n longTrackersFundingValue: string;\n shortTrackersFundingValue: string;\n longTrackersBaseMultiplier: string;\n shortTrackersBaseMultiplier: string;\n longTrackersAdlUnwindPrice: string;\n shortTrackersAdlUnwindPrice: string;\n /** Block the market trackers were observed at (optional; enables the staleness guard). */\n blockNumber?: string | null;\n};\n\n/** Structured cause for service metrics; calculation still fails closed. */\nexport class SettlementTrackerError extends Error {\n constructor(\n public readonly marketId: string,\n public readonly reason: 'missing' | 'inconsistent',\n ) {\n super(\n reason === 'missing'\n ? `Missing market trackers for ${marketId}`\n : `Inconsistent ADL trackers for ${marketId}`,\n );\n // common targets ES5; restore Error subclass identity after downleveling.\n Object.setPrototypeOf(this, new.target.prototype);\n this.name = 'SettlementTrackerError';\n }\n}\n\nconst WAD = new BigNumber('1000000000000000000');\nconst integer = (value: { toString(): string } | null, field: string) => {\n const result = new BigNumber(value?.toString() ?? NaN);\n if (!result.isInteger()) throw new Error(`Missing or invalid ${field}`);\n return result;\n};\nconst optionalBlock = (value: { toString(): string } | null | undefined) => {\n if (value === null || value === undefined) return undefined;\n const result = new BigNumber(value.toString());\n return result.isInteger() ? result : undefined;\n};\n/**\n * Market trackers older than the position's own snapshot carry nothing the\n * stored position does not already reflect. Off-chain tracker feeds can lag\n * the position stream.\n */\nexport function trackersBehindPosition(\n position: Pick<RealizedBalancePosition, 'block_number'>,\n trackers: Pick<RealizedBalanceTrackers, 'blockNumber'>,\n): boolean {\n const positionBlock = optionalBlock(position.block_number);\n const trackerBlock = optionalBlock(trackers.blockNumber);\n return !!positionBlock && !!trackerBlock && positionBlock.gt(trackerBlock);\n}\n\n/**\n * The trackers to ADL-adjust a position's quantity with, guarded the way its\n * settlement is: behind the position, its own multiplier and unwind price stand in.\n */\nexport function positionAdjustmentTrackers<\n T extends Pick<\n RealizedBalanceTrackers,\n | 'longTrackersBaseMultiplier'\n | 'shortTrackersBaseMultiplier'\n | 'longTrackersAdlUnwindPrice'\n | 'shortTrackersAdlUnwindPrice'\n | 'blockNumber'\n >,\n>(\n position: Pick<\n RealizedBalancePosition,\n 'block_number' | 'base_multiplier' | 'adl_unwind_price'\n >,\n trackers: T,\n): T {\n if (\n !trackersBehindPosition(position, trackers) ||\n position.base_multiplier === null ||\n position.adl_unwind_price === null\n )\n return trackers;\n const multiplier = position.base_multiplier.toString();\n const unwind = position.adl_unwind_price.toString();\n return {\n ...trackers,\n longTrackersBaseMultiplier: multiplier,\n shortTrackersBaseMultiplier: multiplier,\n longTrackersAdlUnwindPrice: unwind,\n shortTrackersAdlUnwindPrice: unwind,\n };\n}\n\nconst mulWad = (a: BigNumber, b: BigNumber) =>\n a.times(b).dividedToIntegerBy(WAD);\nconst divWad = (a: BigNumber, b: BigNumber) =>\n a.times(WAD).dividedToIntegerBy(b);\n\n/** Mirrors perpOB updatePerpPosition, including PRBMath truncation at each step. */\nexport function calculateSettledPositionPnl(\n position: RealizedBalancePosition,\n trackers: RealizedBalanceTrackers | undefined,\n onGuarded?: () => void,\n): BigNumber {\n const base = integer(position.base, 'position base');\n const realized = integer(position.realized_pnl, 'realized PnL');\n if (base.isZero()) return realized;\n if (!trackers)\n throw new SettlementTrackerError(position.market_id.toString(), 'missing');\n\n const long = base.isPositive();\n const funding = integer(\n long\n ? trackers.longTrackersFundingValue\n : trackers.shortTrackersFundingValue,\n 'market funding',\n );\n const multiplier = integer(\n long\n ? trackers.longTrackersBaseMultiplier\n : trackers.shortTrackersBaseMultiplier,\n 'market multiplier',\n );\n const unwind = integer(\n long\n ? trackers.longTrackersAdlUnwindPrice\n : trackers.shortTrackersAdlUnwindPrice,\n 'market unwind price',\n );\n const oldMultiplier = integer(\n position.base_multiplier,\n 'position multiplier',\n );\n const oldUnwind = integer(position.adl_unwind_price, 'position unwind price');\n const oldFunding = integer(position.funding_value, 'position funding');\n if (\n funding.eq(oldFunding) &&\n multiplier.eq(oldMultiplier) &&\n unwind.eq(oldUnwind)\n )\n return realized;\n\n // Market trackers older than the position's own snapshot carry no new\n // cashflow: the stored realized PnL already settled everything up to the\n // position's block. Treat that window as \"nothing accrued\" instead of\n // projecting a delta backwards (wrong-sign funding, or an ADL guard failure\n // below).\n if (trackersBehindPosition(position, trackers)) {\n onGuarded?.();\n return realized;\n }\n\n if (\n oldMultiplier.lte(0) ||\n multiplier.lt(0) ||\n multiplier.gt(oldMultiplier) ||\n unwind.lt(oldUnwind)\n ) {\n throw new SettlementTrackerError(\n position.market_id.toString(),\n 'inconsistent',\n );\n }\n const fundingCashflow = mulWad(\n divWad(funding.minus(oldFunding), oldMultiplier),\n base.negated(),\n );\n const unwindDelta = divWad(unwind.minus(oldUnwind), oldMultiplier);\n const initialPrice = mulWad(\n WAD.minus(divWad(multiplier, oldMultiplier)),\n integer(position.last_price, 'position price'),\n );\n const adlCashflow = mulWad(base, unwindDelta.minus(initialPrice));\n return realized.plus(fundingCashflow).plus(adlCashflow);\n}\n\n/**\n * Returns raw E18 PnL aligned to collateral units. The instrument floors EACH\n * market's PnL to quote-token precision before Core aggregates collateral info.\n * Funding is the stored market tracker delta; do not extrapolate it with time.\n */\nexport function calculateSettledAccountPnl(\n positions: RealizedBalancePosition[],\n trackers: Partial<Record<string, RealizedBalanceTrackers>>,\n collateralDecimals: number,\n onGuarded?: () => void,\n): BigNumber {\n return positions.reduce((sum, position) => {\n const pnl = calculateSettledPositionPnl(\n position,\n trackers[position.market_id.toString()],\n onGuarded,\n );\n const rounded = pnl\n .shiftedBy(collateralDecimals - 18)\n .integerValue(BigNumber.ROUND_FLOOR)\n .shiftedBy(18 - collateralDecimals);\n return sum.plus(rounded);\n }, new BigNumber(0));\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reyaxyz/common",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.374.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"test:coverage": "npx jest test --coverage",
|
|
42
42
|
"generate:coverage-badges": "npx istanbul-badges-readme --silent"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "c79e1c00f842259ddcb7c435ed799ea0b49e9939"
|
|
45
45
|
}
|
|
@@ -52,6 +52,57 @@ const optionalBlock = (value: { toString(): string } | null | undefined) => {
|
|
|
52
52
|
const result = new BigNumber(value.toString());
|
|
53
53
|
return result.isInteger() ? result : undefined;
|
|
54
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* Market trackers older than the position's own snapshot carry nothing the
|
|
57
|
+
* stored position does not already reflect. Off-chain tracker feeds can lag
|
|
58
|
+
* the position stream.
|
|
59
|
+
*/
|
|
60
|
+
export function trackersBehindPosition(
|
|
61
|
+
position: Pick<RealizedBalancePosition, 'block_number'>,
|
|
62
|
+
trackers: Pick<RealizedBalanceTrackers, 'blockNumber'>,
|
|
63
|
+
): boolean {
|
|
64
|
+
const positionBlock = optionalBlock(position.block_number);
|
|
65
|
+
const trackerBlock = optionalBlock(trackers.blockNumber);
|
|
66
|
+
return !!positionBlock && !!trackerBlock && positionBlock.gt(trackerBlock);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The trackers to ADL-adjust a position's quantity with, guarded the way its
|
|
71
|
+
* settlement is: behind the position, its own multiplier and unwind price stand in.
|
|
72
|
+
*/
|
|
73
|
+
export function positionAdjustmentTrackers<
|
|
74
|
+
T extends Pick<
|
|
75
|
+
RealizedBalanceTrackers,
|
|
76
|
+
| 'longTrackersBaseMultiplier'
|
|
77
|
+
| 'shortTrackersBaseMultiplier'
|
|
78
|
+
| 'longTrackersAdlUnwindPrice'
|
|
79
|
+
| 'shortTrackersAdlUnwindPrice'
|
|
80
|
+
| 'blockNumber'
|
|
81
|
+
>,
|
|
82
|
+
>(
|
|
83
|
+
position: Pick<
|
|
84
|
+
RealizedBalancePosition,
|
|
85
|
+
'block_number' | 'base_multiplier' | 'adl_unwind_price'
|
|
86
|
+
>,
|
|
87
|
+
trackers: T,
|
|
88
|
+
): T {
|
|
89
|
+
if (
|
|
90
|
+
!trackersBehindPosition(position, trackers) ||
|
|
91
|
+
position.base_multiplier === null ||
|
|
92
|
+
position.adl_unwind_price === null
|
|
93
|
+
)
|
|
94
|
+
return trackers;
|
|
95
|
+
const multiplier = position.base_multiplier.toString();
|
|
96
|
+
const unwind = position.adl_unwind_price.toString();
|
|
97
|
+
return {
|
|
98
|
+
...trackers,
|
|
99
|
+
longTrackersBaseMultiplier: multiplier,
|
|
100
|
+
shortTrackersBaseMultiplier: multiplier,
|
|
101
|
+
longTrackersAdlUnwindPrice: unwind,
|
|
102
|
+
shortTrackersAdlUnwindPrice: unwind,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
55
106
|
const mulWad = (a: BigNumber, b: BigNumber) =>
|
|
56
107
|
a.times(b).dividedToIntegerBy(WAD);
|
|
57
108
|
const divWad = (a: BigNumber, b: BigNumber) =>
|
|
@@ -103,12 +154,10 @@ export function calculateSettledPositionPnl(
|
|
|
103
154
|
|
|
104
155
|
// Market trackers older than the position's own snapshot carry no new
|
|
105
156
|
// cashflow: the stored realized PnL already settled everything up to the
|
|
106
|
-
// position's block.
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
const trackerBlock = optionalBlock(trackers.blockNumber);
|
|
111
|
-
if (positionBlock && trackerBlock && positionBlock.gt(trackerBlock)) {
|
|
157
|
+
// position's block. Treat that window as "nothing accrued" instead of
|
|
158
|
+
// projecting a delta backwards (wrong-sign funding, or an ADL guard failure
|
|
159
|
+
// below).
|
|
160
|
+
if (trackersBehindPosition(position, trackers)) {
|
|
112
161
|
onGuarded?.();
|
|
113
162
|
return realized;
|
|
114
163
|
}
|