@reyaxyz/sdk 0.124.9 → 0.124.11

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 CHANGED
@@ -6,5 +6,5 @@
6
6
 
7
7
  | Statements | Branches | Functions | Lines |
8
8
  | --------------------------- | ----------------------- | ------------------------- | ----------------- |
9
- | ![Statements](https://img.shields.io/badge/statements-9.29%25-red.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-4.21%25-red.svg?style=flat) | ![Functions](https://img.shields.io/badge/functions-5.49%25-red.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-8.69%25-red.svg?style=flat) |
9
+ | ![Statements](https://img.shields.io/badge/statements-9.2%25-red.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-4.21%25-red.svg?style=flat) | ![Functions](https://img.shields.io/badge/functions-5.49%25-red.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-8.61%25-red.svg?style=flat) |
10
10
 
@@ -126,17 +126,9 @@ var findBestPath = function (amountFrom, tokenFrom, tokenTo, maxSteps) { return
126
126
  case 1:
127
127
  result = _a.sent();
128
128
  // It can happen that the amount from results in a zero amount out
129
- // dues to smaller precision of amount out, resulting in no path
129
+ // due to smaller precision of amount out, resulting in no path
130
130
  if (result.amounts.length == 0) {
131
- return [2 /*return*/, {
132
- amountFrom: amountFrom,
133
- amountTo: 0,
134
- amountInBase: Number(amountFromScaled),
135
- amountOutBase: 0,
136
- adapters: [],
137
- path: [tokenFrom, tokenTo],
138
- recipients: [],
139
- }];
131
+ throw new Error('Amount to be received is zero. Not a viable swap.');
140
132
  }
141
133
  return [2 /*return*/, {
142
134
  amountFrom: (0, common_1.descale)(tokenInfoFrom.decimals)(result.amounts[0]),
@@ -172,7 +164,7 @@ var getPreSwapMarginInfo = function (marginAccountId) { return __awaiter(void 0,
172
164
  });
173
165
  }); };
174
166
  var simulateSwap = function (params) { return __awaiter(void 0, void 0, void 0, function () {
175
- var bestPathResult, simulatedPrice, restModule, markets, market, estimatedPriceImpact, marketReversed, collaterals, tokenFromHaircut, tokenToHaircut, marginInfo, adjustedAmountFrom, adjustedAmountTo, postSwapMargin, marginRatio;
167
+ var bestPathResult, simulatedPrice, restModule, markets, tokenFromPrice, tokenToPrice, estimatedPriceImpact, market, marketReversed, collaterals, tokenFromHaircut, tokenToHaircut, marginInfo, adjustedAmountFrom, adjustedAmountTo, postSwapMargin, marginRatio;
176
168
  var _a, _b;
177
169
  return __generator(this, function (_c) {
178
170
  switch (_c.label) {
@@ -184,13 +176,18 @@ var simulateSwap = function (params) { return __awaiter(void 0, void 0, void 0,
184
176
  return [4 /*yield*/, restModule.getSpotMarkets()];
185
177
  case 2:
186
178
  markets = _c.sent();
179
+ tokenFromPrice = 1;
180
+ tokenToPrice = 1;
181
+ estimatedPriceImpact = 0;
187
182
  market = markets.find(function (m) {
188
183
  return (m.quoteToken.address == params.tokenFrom.toLowerCase() &&
189
184
  m.underlyingAsset.address == params.tokenTo.toLowerCase());
190
185
  });
191
- estimatedPriceImpact = 0;
186
+ // check both directions of the market
192
187
  if (market != undefined) {
193
188
  estimatedPriceImpact = (market.price - simulatedPrice) / market.price;
189
+ tokenFromPrice = market.quoteToken.price;
190
+ tokenToPrice = market.underlyingAsset.price;
194
191
  }
195
192
  else {
196
193
  marketReversed = markets.find(function (m) {
@@ -201,6 +198,8 @@ var simulateSwap = function (params) { return __awaiter(void 0, void 0, void 0,
201
198
  estimatedPriceImpact =
202
199
  (1 / marketReversed.price - simulatedPrice) /
203
200
  (1 / marketReversed.price);
201
+ tokenFromPrice = marketReversed.underlyingAsset.price;
202
+ tokenToPrice = marketReversed.quoteToken.price;
204
203
  }
205
204
  }
206
205
  return [4 /*yield*/, restModule.getCollateralInfo()];
@@ -214,9 +213,10 @@ var simulateSwap = function (params) { return __awaiter(void 0, void 0, void 0,
214
213
  return [4 /*yield*/, getPreSwapMarginInfo(params.marginAccountId)];
215
214
  case 4:
216
215
  marginInfo = _c.sent();
217
- adjustedAmountFrom = bestPathResult.amountFrom * (1 - tokenFromHaircut);
218
- adjustedAmountTo = bestPathResult.amountTo * (1 - tokenToHaircut);
219
- postSwapMargin = marginInfo.preSwapMarginBalance - adjustedAmountFrom + adjustedAmountTo;
216
+ adjustedAmountFrom = bestPathResult.amountFrom * tokenFromPrice * (1 - tokenFromHaircut);
217
+ adjustedAmountTo = bestPathResult.amountTo * tokenToPrice * (1 - tokenToHaircut);
218
+ postSwapMargin = marginInfo.preSwapMarginBalance -
219
+ (adjustedAmountFrom - adjustedAmountTo) * Math.pow(10, 18);
220
220
  marginRatio = (marginInfo.lmr / postSwapMargin) * 100;
221
221
  return [2 /*return*/, {
222
222
  bestPath: bestPathResult,
@@ -1 +1 @@
1
- {"version":3,"file":"simulation.js","sourceRoot":"/","sources":["services/swaps/simulation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ContractType,\n descale,\n getAddress,\n getTokenInfoByAddress,\n scaleV2,\n reyaChainIdRPCMapper,\n ExposureCommand,\n CoreAbi,\n SpotMarketEntity,\n CollateralWithHaircut,\n} from '@reyaxyz/common';\nimport { Contract, ethers } from 'ethers';\nimport {\n FindBestPathResult,\n GetPreSwapMarginInfo,\n SimulateSwapParams,\n SimulateSwapResult,\n} from './types';\nimport { getGeneralRestModuleClient } from '../../config';\nimport { getReyaNetwork } from '../../utils/network';\nimport { DEFAULT_SLIPPAGE } from './swap';\n\nconst CamelotAbi = [\n {\n inputs: [\n {\n internalType: 'uint256',\n name: '_amountIn',\n type: 'uint256',\n },\n {\n internalType: 'address',\n name: '_tokenIn',\n type: 'address',\n },\n {\n internalType: 'address',\n name: '_tokenOut',\n type: 'address',\n },\n {\n internalType: 'address[]',\n name: '_trustedTokens',\n type: 'address[]',\n },\n {\n internalType: 'uint256',\n name: '_maxSteps',\n type: 'uint256',\n },\n ],\n name: 'findBestPath',\n outputs: [\n {\n components: [\n {\n internalType: 'uint256[]',\n name: 'amounts',\n type: 'uint256[]',\n },\n {\n internalType: 'address[]',\n name: 'adapters',\n type: 'address[]',\n },\n {\n internalType: 'address[]',\n name: 'path',\n type: 'address[]',\n },\n {\n internalType: 'address[]',\n name: 'recipients',\n type: 'address[]',\n },\n {\n internalType: 'uint256',\n name: 'gasEstimate',\n type: 'uint256',\n },\n ],\n internalType: 'struct FormattedOffer',\n name: '',\n type: 'tuple',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n];\n\nexport const findBestPath = async (\n amountFrom: number,\n tokenFrom: string,\n tokenTo: string,\n maxSteps?: number,\n): Promise<FindBestPathResult> => {\n const chainId = getReyaNetwork();\n const provider = ethers.getDefaultProvider(\n reyaChainIdRPCMapper[chainId] as string,\n );\n const camelotAddress = getAddress(chainId, ContractType.CAMELOT_YAK_ROUTER);\n const camelot = new Contract(camelotAddress, CamelotAbi, provider);\n\n const tokenInfoFrom = getTokenInfoByAddress(tokenFrom);\n const tokenInfoTo = getTokenInfoByAddress(tokenTo);\n const amountFromScaled = scaleV2(tokenInfoFrom.decimals)(amountFrom);\n\n // amountFrom\n // tokenFrom\n // tokenTo\n // trustedTokens\n // maxSteps\n const result = await camelot.findBestPath(\n amountFromScaled,\n tokenFrom,\n tokenTo,\n [],\n maxSteps || 4,\n );\n\n // It can happen that the amount from results in a zero amount out\n // dues to smaller precision of amount out, resulting in no path\n if (result.amounts.length == 0) {\n return {\n amountFrom: amountFrom,\n amountTo: 0,\n amountInBase: Number(amountFromScaled),\n amountOutBase: 0,\n adapters: [],\n path: [tokenFrom, tokenTo],\n recipients: [],\n };\n }\n\n return {\n amountFrom: descale(tokenInfoFrom.decimals)(result.amounts[0]),\n amountTo: descale(tokenInfoTo.decimals)(result.amounts[1]),\n amountInBase: result.amounts[0],\n amountOutBase: result.amounts[1],\n adapters: Array.from(result[1]),\n path: Array.from(result[2]),\n recipients: Array.from(result[3]),\n };\n};\n\n// Simulates sending the swap directly to Core using the publisher as msg.sender\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst getPreSwapMarginInfo = async (\n marginAccountId: number,\n): Promise<GetPreSwapMarginInfo> => {\n const chainId = getReyaNetwork();\n const provider = ethers.getDefaultProvider(\n reyaChainIdRPCMapper[chainId] as string,\n );\n const core = new Contract(\n getAddress(chainId, ContractType.CORE_PROXY),\n CoreAbi,\n provider,\n );\n\n const result = await core.getUsdNodeMarginInfo(marginAccountId);\n return {\n preSwapMarginBalance: Number(result[1]),\n lmr: Number(result[9]),\n };\n};\n\nexport const simulateSwap = async (\n params: SimulateSwapParams,\n): Promise<SimulateSwapResult> => {\n const bestPathResult = await findBestPath(\n params.amountFrom,\n params.tokenFrom,\n params.tokenTo,\n );\n\n // slippage calculation\n const simulatedPrice = bestPathResult.amountTo / bestPathResult.amountFrom;\n const restModule = getGeneralRestModuleClient();\n const markets: SpotMarketEntity[] = await restModule.getSpotMarkets();\n\n const market = markets.find((m) => {\n return (\n m.quoteToken.address == params.tokenFrom.toLowerCase() &&\n m.underlyingAsset.address == params.tokenTo.toLowerCase()\n );\n });\n let estimatedPriceImpact = 0;\n if (market != undefined) {\n estimatedPriceImpact = (market.price - simulatedPrice) / market.price;\n } else {\n const marketReversed = markets.find((m) => {\n return (\n m.underlyingAsset.address == params.tokenFrom.toLowerCase() &&\n m.quoteToken.address == params.tokenTo.toLowerCase()\n );\n });\n if (marketReversed != undefined) {\n estimatedPriceImpact =\n (1 / marketReversed.price - simulatedPrice) /\n (1 / marketReversed.price);\n }\n }\n\n const collaterals: CollateralWithHaircut[] =\n await restModule.getCollateralInfo();\n const tokenFromHaircut = collaterals.find(\n (c) => c.address == params.tokenFrom.toLowerCase(),\n )?.priceHaircut;\n const tokenToHaircut = collaterals.find(\n (c) => c.address == params.tokenFrom.toLowerCase(),\n )?.priceHaircut;\n\n if (tokenFromHaircut === undefined || tokenToHaircut === undefined) {\n throw new Error('Cannot find collateral tokens');\n }\n\n const marginInfo = await getPreSwapMarginInfo(params.marginAccountId);\n const adjustedAmountFrom = bestPathResult.amountFrom * (1 - tokenFromHaircut);\n const adjustedAmountTo = bestPathResult.amountTo * (1 - tokenToHaircut);\n\n const postSwapMargin =\n marginInfo.preSwapMarginBalance - adjustedAmountFrom + adjustedAmountTo;\n\n // Calculate the margin ratio\n const marginRatio = (marginInfo.lmr / postSwapMargin) * 100;\n\n return {\n bestPath: bestPathResult,\n estimatedPriceImpact: estimatedPriceImpact * 100,\n defaultSlippage: DEFAULT_SLIPPAGE * 100,\n marginRatio: marginRatio,\n marginRatioHealth: ExposureCommand.evaluateHealthStatus(marginRatio),\n };\n};\n"]}
1
+ {"version":3,"file":"simulation.js","sourceRoot":"/","sources":["services/swaps/simulation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ContractType,\n descale,\n getAddress,\n getTokenInfoByAddress,\n scaleV2,\n reyaChainIdRPCMapper,\n ExposureCommand,\n CoreAbi,\n SpotMarketEntity,\n CollateralWithHaircut,\n} from '@reyaxyz/common';\nimport { Contract, ethers } from 'ethers';\nimport {\n FindBestPathResult,\n GetPreSwapMarginInfo,\n SimulateSwapParams,\n SimulateSwapResult,\n} from './types';\nimport { getGeneralRestModuleClient } from '../../config';\nimport { getReyaNetwork } from '../../utils/network';\nimport { DEFAULT_SLIPPAGE } from './swap';\n\nconst CamelotAbi = [\n {\n inputs: [\n {\n internalType: 'uint256',\n name: '_amountIn',\n type: 'uint256',\n },\n {\n internalType: 'address',\n name: '_tokenIn',\n type: 'address',\n },\n {\n internalType: 'address',\n name: '_tokenOut',\n type: 'address',\n },\n {\n internalType: 'address[]',\n name: '_trustedTokens',\n type: 'address[]',\n },\n {\n internalType: 'uint256',\n name: '_maxSteps',\n type: 'uint256',\n },\n ],\n name: 'findBestPath',\n outputs: [\n {\n components: [\n {\n internalType: 'uint256[]',\n name: 'amounts',\n type: 'uint256[]',\n },\n {\n internalType: 'address[]',\n name: 'adapters',\n type: 'address[]',\n },\n {\n internalType: 'address[]',\n name: 'path',\n type: 'address[]',\n },\n {\n internalType: 'address[]',\n name: 'recipients',\n type: 'address[]',\n },\n {\n internalType: 'uint256',\n name: 'gasEstimate',\n type: 'uint256',\n },\n ],\n internalType: 'struct FormattedOffer',\n name: '',\n type: 'tuple',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n];\n\nexport const findBestPath = async (\n amountFrom: number,\n tokenFrom: string,\n tokenTo: string,\n maxSteps?: number,\n): Promise<FindBestPathResult> => {\n const chainId = getReyaNetwork();\n const provider = ethers.getDefaultProvider(\n reyaChainIdRPCMapper[chainId] as string,\n );\n const camelotAddress = getAddress(chainId, ContractType.CAMELOT_YAK_ROUTER);\n const camelot = new Contract(camelotAddress, CamelotAbi, provider);\n\n const tokenInfoFrom = getTokenInfoByAddress(tokenFrom);\n const tokenInfoTo = getTokenInfoByAddress(tokenTo);\n const amountFromScaled = scaleV2(tokenInfoFrom.decimals)(amountFrom);\n\n // amountFrom\n // tokenFrom\n // tokenTo\n // trustedTokens\n // maxSteps\n const result = await camelot.findBestPath(\n amountFromScaled,\n tokenFrom,\n tokenTo,\n [],\n maxSteps || 4,\n );\n\n // It can happen that the amount from results in a zero amount out\n // due to smaller precision of amount out, resulting in no path\n if (result.amounts.length == 0) {\n throw new Error('Amount to be received is zero. Not a viable swap.');\n }\n\n return {\n amountFrom: descale(tokenInfoFrom.decimals)(result.amounts[0]),\n amountTo: descale(tokenInfoTo.decimals)(result.amounts[1]),\n amountInBase: result.amounts[0],\n amountOutBase: result.amounts[1],\n adapters: Array.from(result[1]),\n path: Array.from(result[2]),\n recipients: Array.from(result[3]),\n };\n};\n\n// Simulates sending the swap directly to Core using the publisher as msg.sender\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst getPreSwapMarginInfo = async (\n marginAccountId: number,\n): Promise<GetPreSwapMarginInfo> => {\n const chainId = getReyaNetwork();\n const provider = ethers.getDefaultProvider(\n reyaChainIdRPCMapper[chainId] as string,\n );\n const core = new Contract(\n getAddress(chainId, ContractType.CORE_PROXY),\n CoreAbi,\n provider,\n );\n\n const result = await core.getUsdNodeMarginInfo(marginAccountId);\n return {\n preSwapMarginBalance: Number(result[1]),\n lmr: Number(result[9]),\n };\n};\n\nexport const simulateSwap = async (\n params: SimulateSwapParams,\n): Promise<SimulateSwapResult> => {\n const bestPathResult = await findBestPath(\n params.amountFrom,\n params.tokenFrom,\n params.tokenTo,\n );\n\n // slippage calculation\n const simulatedPrice = bestPathResult.amountTo / bestPathResult.amountFrom;\n const restModule = getGeneralRestModuleClient();\n const markets: SpotMarketEntity[] = await restModule.getSpotMarkets();\n\n let tokenFromPrice = 1;\n let tokenToPrice = 1;\n let estimatedPriceImpact = 0;\n\n const market = markets.find((m) => {\n return (\n m.quoteToken.address == params.tokenFrom.toLowerCase() &&\n m.underlyingAsset.address == params.tokenTo.toLowerCase()\n );\n });\n\n // check both directions of the market\n if (market != undefined) {\n estimatedPriceImpact = (market.price - simulatedPrice) / market.price;\n tokenFromPrice = market.quoteToken.price;\n tokenToPrice = market.underlyingAsset.price;\n } else {\n const marketReversed = markets.find((m) => {\n return (\n m.underlyingAsset.address == params.tokenFrom.toLowerCase() &&\n m.quoteToken.address == params.tokenTo.toLowerCase()\n );\n });\n if (marketReversed != undefined) {\n estimatedPriceImpact =\n (1 / marketReversed.price - simulatedPrice) /\n (1 / marketReversed.price);\n tokenFromPrice = marketReversed.underlyingAsset.price;\n tokenToPrice = marketReversed.quoteToken.price;\n }\n }\n\n const collaterals: CollateralWithHaircut[] =\n await restModule.getCollateralInfo();\n const tokenFromHaircut = collaterals.find(\n (c) => c.address == params.tokenFrom.toLowerCase(),\n )?.priceHaircut;\n const tokenToHaircut = collaterals.find(\n (c) => c.address == params.tokenFrom.toLowerCase(),\n )?.priceHaircut;\n\n if (tokenFromHaircut === undefined || tokenToHaircut === undefined) {\n throw new Error('Cannot find collateral tokens');\n }\n\n const marginInfo = await getPreSwapMarginInfo(params.marginAccountId);\n const adjustedAmountFrom =\n bestPathResult.amountFrom * tokenFromPrice * (1 - tokenFromHaircut);\n const adjustedAmountTo =\n bestPathResult.amountTo * tokenToPrice * (1 - tokenToHaircut);\n\n const postSwapMargin =\n marginInfo.preSwapMarginBalance -\n (adjustedAmountFrom - adjustedAmountTo) * 10 ** 18;\n\n // Calculate the margin ratio\n const marginRatio = (marginInfo.lmr / postSwapMargin) * 100;\n\n return {\n bestPath: bestPathResult,\n estimatedPriceImpact: estimatedPriceImpact * 100,\n defaultSlippage: DEFAULT_SLIPPAGE * 100,\n marginRatio: marginRatio,\n marginRatioHealth: ExposureCommand.evaluateHealthStatus(marginRatio),\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"simulation.d.ts","sourceRoot":"/","sources":["services/swaps/simulation.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,kBAAkB,EAElB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AA0EjB,eAAO,MAAM,YAAY,eACX,MAAM,aACP,MAAM,WACR,MAAM,aACJ,MAAM,KAChB,QAAQ,kBAAkB,CAgD5B,CAAC;AAwBF,eAAO,MAAM,YAAY,WACf,kBAAkB,KACzB,QAAQ,kBAAkB,CAiE5B,CAAC"}
1
+ {"version":3,"file":"simulation.d.ts","sourceRoot":"/","sources":["services/swaps/simulation.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,kBAAkB,EAElB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AA0EjB,eAAO,MAAM,YAAY,eACX,MAAM,aACP,MAAM,WACR,MAAM,aACJ,MAAM,KAChB,QAAQ,kBAAkB,CAwC5B,CAAC;AAwBF,eAAO,MAAM,YAAY,WACf,kBAAkB,KACzB,QAAQ,kBAAkB,CA6E5B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reyaxyz/sdk",
3
- "version": "0.124.9",
3
+ "version": "0.124.11",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org"
@@ -29,11 +29,11 @@
29
29
  "generate:coverage-badges": "npx istanbul-badges-readme --silent"
30
30
  },
31
31
  "dependencies": {
32
- "@reyaxyz/common": "0.230.0",
32
+ "@reyaxyz/common": "0.230.1",
33
33
  "axios": "^1.6.2",
34
34
  "bignumber.js": "^9.1.2",
35
35
  "ethers": "6.9.0"
36
36
  },
37
37
  "packageManager": "pnpm@8.3.1",
38
- "gitHead": "535fb6356a154bbe5dd57eecc42d7c0ba920c8b0"
38
+ "gitHead": "3137269f3cd615f9ab9ca6d2ad7a315466e27bbf"
39
39
  }
@@ -121,17 +121,9 @@ export const findBestPath = async (
121
121
  );
122
122
 
123
123
  // It can happen that the amount from results in a zero amount out
124
- // dues to smaller precision of amount out, resulting in no path
124
+ // due to smaller precision of amount out, resulting in no path
125
125
  if (result.amounts.length == 0) {
126
- return {
127
- amountFrom: amountFrom,
128
- amountTo: 0,
129
- amountInBase: Number(amountFromScaled),
130
- amountOutBase: 0,
131
- adapters: [],
132
- path: [tokenFrom, tokenTo],
133
- recipients: [],
134
- };
126
+ throw new Error('Amount to be received is zero. Not a viable swap.');
135
127
  }
136
128
 
137
129
  return {
@@ -181,15 +173,22 @@ export const simulateSwap = async (
181
173
  const restModule = getGeneralRestModuleClient();
182
174
  const markets: SpotMarketEntity[] = await restModule.getSpotMarkets();
183
175
 
176
+ let tokenFromPrice = 1;
177
+ let tokenToPrice = 1;
178
+ let estimatedPriceImpact = 0;
179
+
184
180
  const market = markets.find((m) => {
185
181
  return (
186
182
  m.quoteToken.address == params.tokenFrom.toLowerCase() &&
187
183
  m.underlyingAsset.address == params.tokenTo.toLowerCase()
188
184
  );
189
185
  });
190
- let estimatedPriceImpact = 0;
186
+
187
+ // check both directions of the market
191
188
  if (market != undefined) {
192
189
  estimatedPriceImpact = (market.price - simulatedPrice) / market.price;
190
+ tokenFromPrice = market.quoteToken.price;
191
+ tokenToPrice = market.underlyingAsset.price;
193
192
  } else {
194
193
  const marketReversed = markets.find((m) => {
195
194
  return (
@@ -201,6 +200,8 @@ export const simulateSwap = async (
201
200
  estimatedPriceImpact =
202
201
  (1 / marketReversed.price - simulatedPrice) /
203
202
  (1 / marketReversed.price);
203
+ tokenFromPrice = marketReversed.underlyingAsset.price;
204
+ tokenToPrice = marketReversed.quoteToken.price;
204
205
  }
205
206
  }
206
207
 
@@ -218,11 +219,14 @@ export const simulateSwap = async (
218
219
  }
219
220
 
220
221
  const marginInfo = await getPreSwapMarginInfo(params.marginAccountId);
221
- const adjustedAmountFrom = bestPathResult.amountFrom * (1 - tokenFromHaircut);
222
- const adjustedAmountTo = bestPathResult.amountTo * (1 - tokenToHaircut);
222
+ const adjustedAmountFrom =
223
+ bestPathResult.amountFrom * tokenFromPrice * (1 - tokenFromHaircut);
224
+ const adjustedAmountTo =
225
+ bestPathResult.amountTo * tokenToPrice * (1 - tokenToHaircut);
223
226
 
224
227
  const postSwapMargin =
225
- marginInfo.preSwapMarginBalance - adjustedAmountFrom + adjustedAmountTo;
228
+ marginInfo.preSwapMarginBalance -
229
+ (adjustedAmountFrom - adjustedAmountTo) * 10 ** 18;
226
230
 
227
231
  // Calculate the margin ratio
228
232
  const marginRatio = (marginInfo.lmr / postSwapMargin) * 100;