@reyaxyz/api-sdk 0.71.0 → 0.72.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/clients/modules/isolated-order.simulation/index.js +156 -0
- package/dist/clients/modules/isolated-order.simulation/index.js.map +1 -0
- package/dist/clients/modules/isolated-order.simulation/types.js +3 -0
- package/dist/clients/modules/isolated-order.simulation/types.js.map +1 -0
- package/dist/types/clients/modules/isolated-order.simulation/index.d.ts +13 -0
- package/dist/types/clients/modules/isolated-order.simulation/index.d.ts.map +1 -0
- package/dist/types/clients/modules/isolated-order.simulation/types.d.ts +27 -0
- package/dist/types/clients/modules/isolated-order.simulation/types.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/clients/modules/isolated-order.simulation/index.ts +230 -0
- package/src/clients/modules/isolated-order.simulation/types.ts +31 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
var common_1 = require("@reyaxyz/common");
|
|
43
|
+
var bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
44
|
+
var IsolatedOrderSimulationClient = /** @class */ (function () {
|
|
45
|
+
function IsolatedOrderSimulationClient(accountClient) {
|
|
46
|
+
this.loadedData = null;
|
|
47
|
+
// Constructor added
|
|
48
|
+
this.accountClient = accountClient;
|
|
49
|
+
}
|
|
50
|
+
// Method to asynchronously load data based on marketId and accountId
|
|
51
|
+
IsolatedOrderSimulationClient.prototype.arm = function (params) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
53
|
+
var _a;
|
|
54
|
+
return __generator(this, function (_b) {
|
|
55
|
+
switch (_b.label) {
|
|
56
|
+
case 0:
|
|
57
|
+
_a = this;
|
|
58
|
+
return [4 /*yield*/, this.fetchMarketData(params.marketId, params.marginAccountId)];
|
|
59
|
+
case 1:
|
|
60
|
+
_a.loadedData = _b.sent();
|
|
61
|
+
return [2 /*return*/];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
IsolatedOrderSimulationClient.prototype.fetchMarketData = function (marketId, accountId) {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
68
|
+
return __generator(this, function (_a) {
|
|
69
|
+
return [2 /*return*/, this.accountClient.getTransactionSimulationInitialData({
|
|
70
|
+
marginAccountId: accountId,
|
|
71
|
+
marketId: marketId,
|
|
72
|
+
})];
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
// Synchronous method to simulate operations
|
|
77
|
+
IsolatedOrderSimulationClient.prototype.simulate = function (params) {
|
|
78
|
+
if (!this.loadedData) {
|
|
79
|
+
throw new Error('Data not loaded. Call arm() first.');
|
|
80
|
+
}
|
|
81
|
+
var amount = (0, bignumber_js_1.default)(params.amount)
|
|
82
|
+
.div(this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id])
|
|
83
|
+
.toNumber();
|
|
84
|
+
var userAccountExposure = new common_1.ExposureCommand(this.loadedData.exposureDataAccount.accountId, this.loadedData.exposureDataAccount.rootCollateralPoolId, this.loadedData.exposureDataAccount.oraclePricePerMarket, this.loadedData.exposureDataAccount.accountBalancePerAsset, this.loadedData.exposureDataAccount.groupedByCollateral, this.loadedData.exposureDataAccount.riskMultipliers, this.loadedData.exposureDataAccount.riskMatrices, this.loadedData.exposureDataAccount.exchangeInfoPerAsset, this.loadedData.exposureDataAccount.positionInfoMarketConfiguration, this.loadedData.exposureDataAccount.uniqueTokenAddresses, this.loadedData.exposureDataAccount.uniqueQuoteCollaterals, this.loadedData.exposureDataAccount.tokenMarginInfoPerAsset, this.loadedData.exposureDataAccount.realizedPnLSum, this.loadedData.exposureDataAccount.unrealizedPnLSum, this.loadedData.exposureDataAccount.collateralAddressToExchangePrice);
|
|
85
|
+
var passivePoolExposure = new common_1.ExposureCommand(this.loadedData.exposureDataPassivePool.accountId, this.loadedData.exposureDataPassivePool.rootCollateralPoolId, this.loadedData.exposureDataPassivePool.oraclePricePerMarket, this.loadedData.exposureDataPassivePool.accountBalancePerAsset, this.loadedData.exposureDataPassivePool.groupedByCollateral, this.loadedData.exposureDataPassivePool.riskMultipliers, this.loadedData.exposureDataPassivePool.riskMatrices, this.loadedData.exposureDataPassivePool.exchangeInfoPerAsset, this.loadedData.exposureDataPassivePool.positionInfoMarketConfiguration, this.loadedData.exposureDataPassivePool.uniqueTokenAddresses, this.loadedData.exposureDataPassivePool.uniqueQuoteCollaterals, this.loadedData.exposureDataPassivePool.tokenMarginInfoPerAsset, this.loadedData.exposureDataPassivePool.realizedPnLSum, this.loadedData.exposureDataPassivePool.unrealizedPnLSum, this.loadedData.exposureDataPassivePool.collateralAddressToExchangePrice);
|
|
86
|
+
var slippage = passivePoolExposure.getSlippage((0, bignumber_js_1.default)(amount).negated().toNumber(), this.loadedData.marketConfiguration, this.loadedData.marketStorage);
|
|
87
|
+
var estimatedPrice = common_1.ExposureCommand.calculateEstimatedPrice(this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id], slippage);
|
|
88
|
+
var fees = common_1.ExposureCommand.calculateFee(this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id], amount, this.loadedData.feeParameter);
|
|
89
|
+
/*
|
|
90
|
+
amount of margin in rUSD terms that needs to be transferred from the source account to the destination account,
|
|
91
|
+
this value is equal to size in rUSD terms / leverage
|
|
92
|
+
*/
|
|
93
|
+
var requiredMargin = (0, bignumber_js_1.default)(params.amount)
|
|
94
|
+
.div((0, bignumber_js_1.default)(params.isolatedPositionLeverage))
|
|
95
|
+
.toNumber();
|
|
96
|
+
/*
|
|
97
|
+
max amount of margin in rUSD terms that can be transferred from the source account to the destination account
|
|
98
|
+
that performs the isolated position trade
|
|
99
|
+
*/
|
|
100
|
+
var availableMargin = userAccountExposure.getUsdNodeMarginInfo.initialDelta;
|
|
101
|
+
// todo: p1: handle multiple collateral token cases (currently hardcoding testnet rusd address)
|
|
102
|
+
var newMarginInfoSource = userAccountExposure.getUsdNodeMarginInfoPostEditCollateral(-requiredMargin, '0x26Ee9DfB27f12990D90EC003af7c5E9C19eA2A4c');
|
|
103
|
+
/*
|
|
104
|
+
* Compute Isolated Account Liquidation Margin Requirement Post Transfer + Trade
|
|
105
|
+
* */
|
|
106
|
+
// todo: p2: consider abstracting into pure function + carefully test
|
|
107
|
+
var marketRiskMatrix = this.loadedData.exposureDataAccount.riskMatrices[this.loadedData.marketStorage.risk_block_id];
|
|
108
|
+
var marketDiagonalRiskParam = marketRiskMatrix.matrix[this.loadedData.marketConfiguration.risk_matrix_index][this.loadedData.marketConfiguration.risk_matrix_index];
|
|
109
|
+
var isolatedRiskMatrix = [[marketDiagonalRiskParam]];
|
|
110
|
+
var isolatedFilledExposures = [(0, bignumber_js_1.default)(params.amount)];
|
|
111
|
+
var isolatedLMR = common_1.ExposureCommand.computeLiquidationMarginRequirement(isolatedRiskMatrix, isolatedFilledExposures);
|
|
112
|
+
/*
|
|
113
|
+
* margin balance of the destination account is the requiredMargin which is expected to be transferred
|
|
114
|
+
* to the destination account that performs the isolated trade
|
|
115
|
+
* the liquidation price in this case is trying to estimate what the liquidation price would be all else equal for
|
|
116
|
+
* the market where the trade is being made by the isolated account that is going to be created as part of isolated
|
|
117
|
+
* trade operation
|
|
118
|
+
* */
|
|
119
|
+
var liquidationPrice = common_1.ExposureCommand.calculateLiquidation(requiredMargin, isolatedLMR, this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id], amount);
|
|
120
|
+
var marginRatio = common_1.ExposureCommand.getMarginRatio(newMarginInfoSource);
|
|
121
|
+
var marginRatioHealth = common_1.ExposureCommand.evaluateHealthStatus(marginRatio, newMarginInfoSource);
|
|
122
|
+
var baseSpacing = (0, common_1.amountNormalizer)(this.loadedData.marketConfiguration.base_spacing).toNumber();
|
|
123
|
+
var spotPrice = this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id];
|
|
124
|
+
return {
|
|
125
|
+
estimatedPrice: estimatedPrice,
|
|
126
|
+
estimatedSlippage: slippage * 100,
|
|
127
|
+
fees: fees,
|
|
128
|
+
liquidationPrice: liquidationPrice.toNumber(),
|
|
129
|
+
marginRatio: marginRatio * 100,
|
|
130
|
+
marginRatioHealth: marginRatioHealth,
|
|
131
|
+
snappedAmount: this.roundToBaseSpacing(amount, baseSpacing) * spotPrice,
|
|
132
|
+
snappedAmountInBase: this.roundToBaseSpacing(amount, baseSpacing),
|
|
133
|
+
availableMargin: availableMargin,
|
|
134
|
+
requiredMargin: requiredMargin,
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
IsolatedOrderSimulationClient.prototype.convertValue = function (params) {
|
|
138
|
+
if (!this.loadedData) {
|
|
139
|
+
throw new Error('Data not loaded. Call arm() first.');
|
|
140
|
+
}
|
|
141
|
+
if (!params.fromBase)
|
|
142
|
+
return (0, bignumber_js_1.default)(params.amount)
|
|
143
|
+
.div(this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id])
|
|
144
|
+
.toNumber();
|
|
145
|
+
else
|
|
146
|
+
return (0, bignumber_js_1.default)(params.amount)
|
|
147
|
+
.times(this.loadedData.exposureDataPassivePool.oraclePricePerMarket[this.loadedData.marketConfiguration.market_id])
|
|
148
|
+
.toNumber();
|
|
149
|
+
};
|
|
150
|
+
IsolatedOrderSimulationClient.prototype.roundToBaseSpacing = function (amount, baseSpacing) {
|
|
151
|
+
return Math.floor(amount / baseSpacing) * baseSpacing;
|
|
152
|
+
};
|
|
153
|
+
return IsolatedOrderSimulationClient;
|
|
154
|
+
}());
|
|
155
|
+
exports.default = IsolatedOrderSimulationClient;
|
|
156
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"/","sources":["clients/modules/isolated-order.simulation/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n SimulateIsolatedOrderEntity,\n IsolatedOrderSimulationConvertValueParams,\n IsolatedOrderSimulationConvertValueResult,\n IsolatedOrderSimulationLoadDataParams,\n IsolatedOrderSimulationSimulateParams,\n} from './types';\nimport AccountClient from '../account';\nimport {\n amountNormalizer,\n ExposureCommand,\n TradeSimulationState,\n} from '@reyaxyz/common';\nimport BigNumber from 'bignumber.js';\n\nexport default class IsolatedOrderSimulationClient {\n private loadedData: TradeSimulationState | null = null;\n private accountClient: AccountClient;\n constructor(accountClient: AccountClient) {\n // Constructor added\n this.accountClient = accountClient;\n }\n\n // Method to asynchronously load data based on marketId and accountId\n async arm(params: IsolatedOrderSimulationLoadDataParams): Promise<void> {\n this.loadedData = await this.fetchMarketData(\n params.marketId,\n params.marginAccountId,\n );\n }\n\n private async fetchMarketData(\n marketId: number,\n accountId: number,\n ): Promise<TradeSimulationState> {\n return this.accountClient.getTransactionSimulationInitialData({\n marginAccountId: accountId,\n marketId: marketId,\n });\n }\n\n // Synchronous method to simulate operations\n simulate(\n params: IsolatedOrderSimulationSimulateParams,\n ): SimulateIsolatedOrderEntity {\n if (!this.loadedData) {\n throw new Error('Data not loaded. Call arm() first.');\n }\n\n const amount = BigNumber(params.amount)\n .div(\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ],\n )\n .toNumber();\n\n const userAccountExposure = new ExposureCommand(\n this.loadedData.exposureDataAccount.accountId,\n this.loadedData.exposureDataAccount.rootCollateralPoolId,\n this.loadedData.exposureDataAccount.oraclePricePerMarket,\n this.loadedData.exposureDataAccount.accountBalancePerAsset,\n this.loadedData.exposureDataAccount.groupedByCollateral,\n this.loadedData.exposureDataAccount.riskMultipliers,\n this.loadedData.exposureDataAccount.riskMatrices,\n this.loadedData.exposureDataAccount.exchangeInfoPerAsset,\n this.loadedData.exposureDataAccount.positionInfoMarketConfiguration,\n this.loadedData.exposureDataAccount.uniqueTokenAddresses,\n this.loadedData.exposureDataAccount.uniqueQuoteCollaterals,\n this.loadedData.exposureDataAccount.tokenMarginInfoPerAsset,\n this.loadedData.exposureDataAccount.realizedPnLSum,\n this.loadedData.exposureDataAccount.unrealizedPnLSum,\n this.loadedData.exposureDataAccount.collateralAddressToExchangePrice,\n );\n\n const passivePoolExposure = new ExposureCommand(\n this.loadedData.exposureDataPassivePool.accountId,\n this.loadedData.exposureDataPassivePool.rootCollateralPoolId,\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket,\n this.loadedData.exposureDataPassivePool.accountBalancePerAsset,\n this.loadedData.exposureDataPassivePool.groupedByCollateral,\n this.loadedData.exposureDataPassivePool.riskMultipliers,\n this.loadedData.exposureDataPassivePool.riskMatrices,\n this.loadedData.exposureDataPassivePool.exchangeInfoPerAsset,\n this.loadedData.exposureDataPassivePool.positionInfoMarketConfiguration,\n this.loadedData.exposureDataPassivePool.uniqueTokenAddresses,\n this.loadedData.exposureDataPassivePool.uniqueQuoteCollaterals,\n this.loadedData.exposureDataPassivePool.tokenMarginInfoPerAsset,\n this.loadedData.exposureDataPassivePool.realizedPnLSum,\n this.loadedData.exposureDataPassivePool.unrealizedPnLSum,\n this.loadedData.exposureDataPassivePool.collateralAddressToExchangePrice,\n );\n\n const slippage = passivePoolExposure.getSlippage(\n BigNumber(amount).negated().toNumber(),\n this.loadedData.marketConfiguration,\n this.loadedData.marketStorage,\n );\n const estimatedPrice = ExposureCommand.calculateEstimatedPrice(\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ],\n slippage,\n );\n\n const fees = ExposureCommand.calculateFee(\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ],\n amount,\n this.loadedData.feeParameter,\n );\n\n /*\n amount of margin in rUSD terms that needs to be transferred from the source account to the destination account,\n this value is equal to size in rUSD terms / leverage\n */\n\n const requiredMargin = BigNumber(params.amount)\n .div(BigNumber(params.isolatedPositionLeverage))\n .toNumber();\n\n /*\n max amount of margin in rUSD terms that can be transferred from the source account to the destination account\n that performs the isolated position trade\n */\n const availableMargin =\n userAccountExposure.getUsdNodeMarginInfo.initialDelta;\n\n // todo: p1: handle multiple collateral token cases (currently hardcoding testnet rusd address)\n const newMarginInfoSource =\n userAccountExposure.getUsdNodeMarginInfoPostEditCollateral(\n -requiredMargin,\n '0x26Ee9DfB27f12990D90EC003af7c5E9C19eA2A4c',\n );\n\n /*\n * Compute Isolated Account Liquidation Margin Requirement Post Transfer + Trade\n * */\n // todo: p2: consider abstracting into pure function + carefully test\n const marketRiskMatrix =\n this.loadedData.exposureDataAccount.riskMatrices[\n this.loadedData.marketStorage.risk_block_id\n ];\n const marketDiagonalRiskParam =\n marketRiskMatrix.matrix[\n this.loadedData.marketConfiguration.risk_matrix_index\n ][this.loadedData.marketConfiguration.risk_matrix_index];\n const isolatedRiskMatrix: BigNumber[][] = [[marketDiagonalRiskParam]];\n const isolatedFilledExposures: BigNumber[] = [BigNumber(params.amount)];\n\n const isolatedLMR = ExposureCommand.computeLiquidationMarginRequirement(\n isolatedRiskMatrix,\n isolatedFilledExposures,\n );\n\n /*\n * margin balance of the destination account is the requiredMargin which is expected to be transferred\n * to the destination account that performs the isolated trade\n * the liquidation price in this case is trying to estimate what the liquidation price would be all else equal for\n * the market where the trade is being made by the isolated account that is going to be created as part of isolated\n * trade operation\n * */\n const liquidationPrice = ExposureCommand.calculateLiquidation(\n requiredMargin,\n isolatedLMR,\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ],\n amount,\n );\n\n const marginRatio = ExposureCommand.getMarginRatio(newMarginInfoSource);\n\n const marginRatioHealth = ExposureCommand.evaluateHealthStatus(\n marginRatio,\n newMarginInfoSource,\n );\n\n const baseSpacing = amountNormalizer(\n this.loadedData.marketConfiguration.base_spacing,\n ).toNumber();\n\n const spotPrice =\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ];\n return {\n estimatedPrice: estimatedPrice,\n estimatedSlippage: slippage * 100,\n fees: fees,\n liquidationPrice: liquidationPrice.toNumber(),\n marginRatio: marginRatio * 100,\n marginRatioHealth: marginRatioHealth,\n snappedAmount: this.roundToBaseSpacing(amount, baseSpacing) * spotPrice,\n snappedAmountInBase: this.roundToBaseSpacing(amount, baseSpacing),\n availableMargin: availableMargin,\n requiredMargin: requiredMargin,\n } as SimulateIsolatedOrderEntity;\n }\n\n convertValue(\n params: IsolatedOrderSimulationConvertValueParams,\n ): IsolatedOrderSimulationConvertValueResult {\n if (!this.loadedData) {\n throw new Error('Data not loaded. Call arm() first.');\n }\n\n if (!params.fromBase)\n return BigNumber(params.amount)\n .div(\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ],\n )\n .toNumber();\n else\n return BigNumber(params.amount)\n .times(\n this.loadedData.exposureDataPassivePool.oraclePricePerMarket[\n this.loadedData.marketConfiguration.market_id\n ],\n )\n .toNumber();\n }\n\n roundToBaseSpacing(amount: number, baseSpacing: number): number {\n return Math.floor(amount / baseSpacing) * baseSpacing;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"/","sources":["clients/modules/isolated-order.simulation/types.ts"],"names":[],"mappings":"","sourcesContent":["import { MarginAccountEntity, MarketEntity } from '@reyaxyz/common';\n\nexport type IsolatedOrderSimulationLoadDataParams = {\n marketId: MarketEntity['id'];\n marginAccountId: MarginAccountEntity['id'];\n};\n\nexport type IsolatedOrderSimulationSimulateParams = {\n amount: number; // position size in rUSD terms, + for long | - for short\n isolatedPositionLeverage: number; // leverage chosen for isolated position trade\n};\n\nexport type IsolatedOrderSimulationConvertValueParams = {\n amount: number;\n fromBase: boolean;\n};\n\nexport type SimulateIsolatedOrderEntity = {\n liquidationPrice: number;\n fees: number;\n estimatedPrice: number;\n estimatedSlippage: number;\n marginRatio: MarginAccountEntity['marginRatioPercentage'];\n marginRatioHealth: MarginAccountEntity['marginRatioHealth'];\n snappedAmount: number;\n snappedAmountInBase: number;\n availableMargin: number;\n requiredMargin: number;\n};\n\nexport type IsolatedOrderSimulationConvertValueResult = number;\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SimulateIsolatedOrderEntity, IsolatedOrderSimulationConvertValueParams, IsolatedOrderSimulationConvertValueResult, IsolatedOrderSimulationLoadDataParams, IsolatedOrderSimulationSimulateParams } from './types';
|
|
2
|
+
import AccountClient from '../account';
|
|
3
|
+
export default class IsolatedOrderSimulationClient {
|
|
4
|
+
private loadedData;
|
|
5
|
+
private accountClient;
|
|
6
|
+
constructor(accountClient: AccountClient);
|
|
7
|
+
arm(params: IsolatedOrderSimulationLoadDataParams): Promise<void>;
|
|
8
|
+
private fetchMarketData;
|
|
9
|
+
simulate(params: IsolatedOrderSimulationSimulateParams): SimulateIsolatedOrderEntity;
|
|
10
|
+
convertValue(params: IsolatedOrderSimulationConvertValueParams): IsolatedOrderSimulationConvertValueResult;
|
|
11
|
+
roundToBaseSpacing(amount: number, baseSpacing: number): number;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"/","sources":["clients/modules/isolated-order.simulation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,yCAAyC,EACzC,yCAAyC,EACzC,qCAAqC,EACrC,qCAAqC,EACtC,MAAM,SAAS,CAAC;AACjB,OAAO,aAAa,MAAM,YAAY,CAAC;AAQvC,MAAM,CAAC,OAAO,OAAO,6BAA6B;IAChD,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,aAAa,CAAgB;gBACzB,aAAa,EAAE,aAAa;IAMlC,GAAG,CAAC,MAAM,EAAE,qCAAqC,GAAG,OAAO,CAAC,IAAI,CAAC;YAOzD,eAAe;IAW7B,QAAQ,CACN,MAAM,EAAE,qCAAqC,GAC5C,2BAA2B;IA6J9B,YAAY,CACV,MAAM,EAAE,yCAAyC,GAChD,yCAAyC;IAuB5C,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;CAGhE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MarginAccountEntity, MarketEntity } from '@reyaxyz/common';
|
|
2
|
+
export type IsolatedOrderSimulationLoadDataParams = {
|
|
3
|
+
marketId: MarketEntity['id'];
|
|
4
|
+
marginAccountId: MarginAccountEntity['id'];
|
|
5
|
+
};
|
|
6
|
+
export type IsolatedOrderSimulationSimulateParams = {
|
|
7
|
+
amount: number;
|
|
8
|
+
isolatedPositionLeverage: number;
|
|
9
|
+
};
|
|
10
|
+
export type IsolatedOrderSimulationConvertValueParams = {
|
|
11
|
+
amount: number;
|
|
12
|
+
fromBase: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type SimulateIsolatedOrderEntity = {
|
|
15
|
+
liquidationPrice: number;
|
|
16
|
+
fees: number;
|
|
17
|
+
estimatedPrice: number;
|
|
18
|
+
estimatedSlippage: number;
|
|
19
|
+
marginRatio: MarginAccountEntity['marginRatioPercentage'];
|
|
20
|
+
marginRatioHealth: MarginAccountEntity['marginRatioHealth'];
|
|
21
|
+
snappedAmount: number;
|
|
22
|
+
snappedAmountInBase: number;
|
|
23
|
+
availableMargin: number;
|
|
24
|
+
requiredMargin: number;
|
|
25
|
+
};
|
|
26
|
+
export type IsolatedOrderSimulationConvertValueResult = number;
|
|
27
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"/","sources":["clients/modules/isolated-order.simulation/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpE,MAAM,MAAM,qCAAqC,GAAG;IAClD,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAC7B,eAAe,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,yCAAyC,GAAG;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,mBAAmB,CAAC,uBAAuB,CAAC,CAAC;IAC1D,iBAAiB,EAAE,mBAAmB,CAAC,mBAAmB,CAAC,CAAC;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,yCAAyC,GAAG,MAAM,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reyaxyz/api-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.72.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"bignumber.js": "^9.1.2"
|
|
38
38
|
},
|
|
39
39
|
"packageManager": "pnpm@9.0.1",
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "cbf9c4faf47872a9122b553e1b7048d2a43a341e"
|
|
41
41
|
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SimulateIsolatedOrderEntity,
|
|
3
|
+
IsolatedOrderSimulationConvertValueParams,
|
|
4
|
+
IsolatedOrderSimulationConvertValueResult,
|
|
5
|
+
IsolatedOrderSimulationLoadDataParams,
|
|
6
|
+
IsolatedOrderSimulationSimulateParams,
|
|
7
|
+
} from './types';
|
|
8
|
+
import AccountClient from '../account';
|
|
9
|
+
import {
|
|
10
|
+
amountNormalizer,
|
|
11
|
+
ExposureCommand,
|
|
12
|
+
TradeSimulationState,
|
|
13
|
+
} from '@reyaxyz/common';
|
|
14
|
+
import BigNumber from 'bignumber.js';
|
|
15
|
+
|
|
16
|
+
export default class IsolatedOrderSimulationClient {
|
|
17
|
+
private loadedData: TradeSimulationState | null = null;
|
|
18
|
+
private accountClient: AccountClient;
|
|
19
|
+
constructor(accountClient: AccountClient) {
|
|
20
|
+
// Constructor added
|
|
21
|
+
this.accountClient = accountClient;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Method to asynchronously load data based on marketId and accountId
|
|
25
|
+
async arm(params: IsolatedOrderSimulationLoadDataParams): Promise<void> {
|
|
26
|
+
this.loadedData = await this.fetchMarketData(
|
|
27
|
+
params.marketId,
|
|
28
|
+
params.marginAccountId,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private async fetchMarketData(
|
|
33
|
+
marketId: number,
|
|
34
|
+
accountId: number,
|
|
35
|
+
): Promise<TradeSimulationState> {
|
|
36
|
+
return this.accountClient.getTransactionSimulationInitialData({
|
|
37
|
+
marginAccountId: accountId,
|
|
38
|
+
marketId: marketId,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Synchronous method to simulate operations
|
|
43
|
+
simulate(
|
|
44
|
+
params: IsolatedOrderSimulationSimulateParams,
|
|
45
|
+
): SimulateIsolatedOrderEntity {
|
|
46
|
+
if (!this.loadedData) {
|
|
47
|
+
throw new Error('Data not loaded. Call arm() first.');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const amount = BigNumber(params.amount)
|
|
51
|
+
.div(
|
|
52
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
53
|
+
this.loadedData.marketConfiguration.market_id
|
|
54
|
+
],
|
|
55
|
+
)
|
|
56
|
+
.toNumber();
|
|
57
|
+
|
|
58
|
+
const userAccountExposure = new ExposureCommand(
|
|
59
|
+
this.loadedData.exposureDataAccount.accountId,
|
|
60
|
+
this.loadedData.exposureDataAccount.rootCollateralPoolId,
|
|
61
|
+
this.loadedData.exposureDataAccount.oraclePricePerMarket,
|
|
62
|
+
this.loadedData.exposureDataAccount.accountBalancePerAsset,
|
|
63
|
+
this.loadedData.exposureDataAccount.groupedByCollateral,
|
|
64
|
+
this.loadedData.exposureDataAccount.riskMultipliers,
|
|
65
|
+
this.loadedData.exposureDataAccount.riskMatrices,
|
|
66
|
+
this.loadedData.exposureDataAccount.exchangeInfoPerAsset,
|
|
67
|
+
this.loadedData.exposureDataAccount.positionInfoMarketConfiguration,
|
|
68
|
+
this.loadedData.exposureDataAccount.uniqueTokenAddresses,
|
|
69
|
+
this.loadedData.exposureDataAccount.uniqueQuoteCollaterals,
|
|
70
|
+
this.loadedData.exposureDataAccount.tokenMarginInfoPerAsset,
|
|
71
|
+
this.loadedData.exposureDataAccount.realizedPnLSum,
|
|
72
|
+
this.loadedData.exposureDataAccount.unrealizedPnLSum,
|
|
73
|
+
this.loadedData.exposureDataAccount.collateralAddressToExchangePrice,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const passivePoolExposure = new ExposureCommand(
|
|
77
|
+
this.loadedData.exposureDataPassivePool.accountId,
|
|
78
|
+
this.loadedData.exposureDataPassivePool.rootCollateralPoolId,
|
|
79
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket,
|
|
80
|
+
this.loadedData.exposureDataPassivePool.accountBalancePerAsset,
|
|
81
|
+
this.loadedData.exposureDataPassivePool.groupedByCollateral,
|
|
82
|
+
this.loadedData.exposureDataPassivePool.riskMultipliers,
|
|
83
|
+
this.loadedData.exposureDataPassivePool.riskMatrices,
|
|
84
|
+
this.loadedData.exposureDataPassivePool.exchangeInfoPerAsset,
|
|
85
|
+
this.loadedData.exposureDataPassivePool.positionInfoMarketConfiguration,
|
|
86
|
+
this.loadedData.exposureDataPassivePool.uniqueTokenAddresses,
|
|
87
|
+
this.loadedData.exposureDataPassivePool.uniqueQuoteCollaterals,
|
|
88
|
+
this.loadedData.exposureDataPassivePool.tokenMarginInfoPerAsset,
|
|
89
|
+
this.loadedData.exposureDataPassivePool.realizedPnLSum,
|
|
90
|
+
this.loadedData.exposureDataPassivePool.unrealizedPnLSum,
|
|
91
|
+
this.loadedData.exposureDataPassivePool.collateralAddressToExchangePrice,
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const slippage = passivePoolExposure.getSlippage(
|
|
95
|
+
BigNumber(amount).negated().toNumber(),
|
|
96
|
+
this.loadedData.marketConfiguration,
|
|
97
|
+
this.loadedData.marketStorage,
|
|
98
|
+
);
|
|
99
|
+
const estimatedPrice = ExposureCommand.calculateEstimatedPrice(
|
|
100
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
101
|
+
this.loadedData.marketConfiguration.market_id
|
|
102
|
+
],
|
|
103
|
+
slippage,
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const fees = ExposureCommand.calculateFee(
|
|
107
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
108
|
+
this.loadedData.marketConfiguration.market_id
|
|
109
|
+
],
|
|
110
|
+
amount,
|
|
111
|
+
this.loadedData.feeParameter,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
amount of margin in rUSD terms that needs to be transferred from the source account to the destination account,
|
|
116
|
+
this value is equal to size in rUSD terms / leverage
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
const requiredMargin = BigNumber(params.amount)
|
|
120
|
+
.div(BigNumber(params.isolatedPositionLeverage))
|
|
121
|
+
.toNumber();
|
|
122
|
+
|
|
123
|
+
/*
|
|
124
|
+
max amount of margin in rUSD terms that can be transferred from the source account to the destination account
|
|
125
|
+
that performs the isolated position trade
|
|
126
|
+
*/
|
|
127
|
+
const availableMargin =
|
|
128
|
+
userAccountExposure.getUsdNodeMarginInfo.initialDelta;
|
|
129
|
+
|
|
130
|
+
// todo: p1: handle multiple collateral token cases (currently hardcoding testnet rusd address)
|
|
131
|
+
const newMarginInfoSource =
|
|
132
|
+
userAccountExposure.getUsdNodeMarginInfoPostEditCollateral(
|
|
133
|
+
-requiredMargin,
|
|
134
|
+
'0x26Ee9DfB27f12990D90EC003af7c5E9C19eA2A4c',
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
/*
|
|
138
|
+
* Compute Isolated Account Liquidation Margin Requirement Post Transfer + Trade
|
|
139
|
+
* */
|
|
140
|
+
// todo: p2: consider abstracting into pure function + carefully test
|
|
141
|
+
const marketRiskMatrix =
|
|
142
|
+
this.loadedData.exposureDataAccount.riskMatrices[
|
|
143
|
+
this.loadedData.marketStorage.risk_block_id
|
|
144
|
+
];
|
|
145
|
+
const marketDiagonalRiskParam =
|
|
146
|
+
marketRiskMatrix.matrix[
|
|
147
|
+
this.loadedData.marketConfiguration.risk_matrix_index
|
|
148
|
+
][this.loadedData.marketConfiguration.risk_matrix_index];
|
|
149
|
+
const isolatedRiskMatrix: BigNumber[][] = [[marketDiagonalRiskParam]];
|
|
150
|
+
const isolatedFilledExposures: BigNumber[] = [BigNumber(params.amount)];
|
|
151
|
+
|
|
152
|
+
const isolatedLMR = ExposureCommand.computeLiquidationMarginRequirement(
|
|
153
|
+
isolatedRiskMatrix,
|
|
154
|
+
isolatedFilledExposures,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* margin balance of the destination account is the requiredMargin which is expected to be transferred
|
|
159
|
+
* to the destination account that performs the isolated trade
|
|
160
|
+
* the liquidation price in this case is trying to estimate what the liquidation price would be all else equal for
|
|
161
|
+
* the market where the trade is being made by the isolated account that is going to be created as part of isolated
|
|
162
|
+
* trade operation
|
|
163
|
+
* */
|
|
164
|
+
const liquidationPrice = ExposureCommand.calculateLiquidation(
|
|
165
|
+
requiredMargin,
|
|
166
|
+
isolatedLMR,
|
|
167
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
168
|
+
this.loadedData.marketConfiguration.market_id
|
|
169
|
+
],
|
|
170
|
+
amount,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const marginRatio = ExposureCommand.getMarginRatio(newMarginInfoSource);
|
|
174
|
+
|
|
175
|
+
const marginRatioHealth = ExposureCommand.evaluateHealthStatus(
|
|
176
|
+
marginRatio,
|
|
177
|
+
newMarginInfoSource,
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
const baseSpacing = amountNormalizer(
|
|
181
|
+
this.loadedData.marketConfiguration.base_spacing,
|
|
182
|
+
).toNumber();
|
|
183
|
+
|
|
184
|
+
const spotPrice =
|
|
185
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
186
|
+
this.loadedData.marketConfiguration.market_id
|
|
187
|
+
];
|
|
188
|
+
return {
|
|
189
|
+
estimatedPrice: estimatedPrice,
|
|
190
|
+
estimatedSlippage: slippage * 100,
|
|
191
|
+
fees: fees,
|
|
192
|
+
liquidationPrice: liquidationPrice.toNumber(),
|
|
193
|
+
marginRatio: marginRatio * 100,
|
|
194
|
+
marginRatioHealth: marginRatioHealth,
|
|
195
|
+
snappedAmount: this.roundToBaseSpacing(amount, baseSpacing) * spotPrice,
|
|
196
|
+
snappedAmountInBase: this.roundToBaseSpacing(amount, baseSpacing),
|
|
197
|
+
availableMargin: availableMargin,
|
|
198
|
+
requiredMargin: requiredMargin,
|
|
199
|
+
} as SimulateIsolatedOrderEntity;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
convertValue(
|
|
203
|
+
params: IsolatedOrderSimulationConvertValueParams,
|
|
204
|
+
): IsolatedOrderSimulationConvertValueResult {
|
|
205
|
+
if (!this.loadedData) {
|
|
206
|
+
throw new Error('Data not loaded. Call arm() first.');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!params.fromBase)
|
|
210
|
+
return BigNumber(params.amount)
|
|
211
|
+
.div(
|
|
212
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
213
|
+
this.loadedData.marketConfiguration.market_id
|
|
214
|
+
],
|
|
215
|
+
)
|
|
216
|
+
.toNumber();
|
|
217
|
+
else
|
|
218
|
+
return BigNumber(params.amount)
|
|
219
|
+
.times(
|
|
220
|
+
this.loadedData.exposureDataPassivePool.oraclePricePerMarket[
|
|
221
|
+
this.loadedData.marketConfiguration.market_id
|
|
222
|
+
],
|
|
223
|
+
)
|
|
224
|
+
.toNumber();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
roundToBaseSpacing(amount: number, baseSpacing: number): number {
|
|
228
|
+
return Math.floor(amount / baseSpacing) * baseSpacing;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MarginAccountEntity, MarketEntity } from '@reyaxyz/common';
|
|
2
|
+
|
|
3
|
+
export type IsolatedOrderSimulationLoadDataParams = {
|
|
4
|
+
marketId: MarketEntity['id'];
|
|
5
|
+
marginAccountId: MarginAccountEntity['id'];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type IsolatedOrderSimulationSimulateParams = {
|
|
9
|
+
amount: number; // position size in rUSD terms, + for long | - for short
|
|
10
|
+
isolatedPositionLeverage: number; // leverage chosen for isolated position trade
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type IsolatedOrderSimulationConvertValueParams = {
|
|
14
|
+
amount: number;
|
|
15
|
+
fromBase: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type SimulateIsolatedOrderEntity = {
|
|
19
|
+
liquidationPrice: number;
|
|
20
|
+
fees: number;
|
|
21
|
+
estimatedPrice: number;
|
|
22
|
+
estimatedSlippage: number;
|
|
23
|
+
marginRatio: MarginAccountEntity['marginRatioPercentage'];
|
|
24
|
+
marginRatioHealth: MarginAccountEntity['marginRatioHealth'];
|
|
25
|
+
snappedAmount: number;
|
|
26
|
+
snappedAmountInBase: number;
|
|
27
|
+
availableMargin: number;
|
|
28
|
+
requiredMargin: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type IsolatedOrderSimulationConvertValueResult = number;
|