@symmio/trading-core 3.1.0 → 3.3.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.
Files changed (128) hide show
  1. package/dist/core/chains/registry.js +1 -1
  2. package/dist/core/chains/registry.js.map +1 -1
  3. package/dist/index.d.ts +4 -2
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +304 -298
  6. package/dist/quotes/get-quote-history/solver-fees.d.ts +39 -0
  7. package/dist/quotes/get-quote-history/solver-fees.d.ts.map +1 -0
  8. package/dist/quotes/get-quote-history/solver-fees.js +36 -0
  9. package/dist/quotes/get-quote-history/solver-fees.js.map +1 -0
  10. package/dist/quotes/get-quote-history/to-history-row.d.ts.map +1 -1
  11. package/dist/quotes/get-quote-history/to-history-row.js +34 -30
  12. package/dist/quotes/get-quote-history/to-history-row.js.map +1 -1
  13. package/dist/quotes/get-quote-history/types.d.ts +20 -0
  14. package/dist/quotes/get-quote-history/types.d.ts.map +1 -1
  15. package/dist/quotes/get-quote-history/types.js.map +1 -1
  16. package/dist/solvers/get-solver-info/get-solver-info.d.ts +36 -0
  17. package/dist/solvers/get-solver-info/get-solver-info.d.ts.map +1 -0
  18. package/dist/solvers/get-solver-info/get-solver-info.js +28 -0
  19. package/dist/solvers/get-solver-info/get-solver-info.js.map +1 -0
  20. package/dist/solvers/get-solver-info/index.d.ts +3 -0
  21. package/dist/solvers/get-solver-info/index.d.ts.map +1 -0
  22. package/dist/solvers/get-solver-info/query.d.ts +29 -0
  23. package/dist/solvers/get-solver-info/query.d.ts.map +1 -0
  24. package/dist/solvers/get-solver-info/query.js +24 -0
  25. package/dist/solvers/get-solver-info/query.js.map +1 -0
  26. package/dist/solvers/instant-close/get-instant-close-fees/get-instant-close-fees.d.ts +152 -0
  27. package/dist/solvers/instant-close/get-instant-close-fees/get-instant-close-fees.d.ts.map +1 -0
  28. package/dist/solvers/instant-close/get-instant-close-fees/get-instant-close-fees.js +82 -0
  29. package/dist/solvers/instant-close/get-instant-close-fees/get-instant-close-fees.js.map +1 -0
  30. package/dist/solvers/instant-close/get-instant-close-fees/index.d.ts +3 -0
  31. package/dist/solvers/instant-close/get-instant-close-fees/index.d.ts.map +1 -0
  32. package/dist/solvers/instant-close/get-instant-close-fees/query.d.ts +37 -0
  33. package/dist/solvers/instant-close/get-instant-close-fees/query.d.ts.map +1 -0
  34. package/dist/solvers/instant-close/get-instant-close-fees/query.js +32 -0
  35. package/dist/solvers/instant-close/get-instant-close-fees/query.js.map +1 -0
  36. package/dist/solvers/instant-close/index.d.ts +1 -0
  37. package/dist/solvers/instant-close/index.d.ts.map +1 -1
  38. package/dist/solvers/instant-close/instant-close/instant-close.d.ts +4 -3
  39. package/dist/solvers/instant-close/instant-close/instant-close.d.ts.map +1 -1
  40. package/dist/solvers/instant-close/instant-close/instant-close.js +26 -22
  41. package/dist/solvers/instant-close/instant-close/instant-close.js.map +1 -1
  42. package/dist/solvers/instant-close/instant-close-bulk/instant-close-bulk.d.ts +2 -0
  43. package/dist/solvers/instant-close/instant-close-bulk/instant-close-bulk.d.ts.map +1 -1
  44. package/dist/solvers/instant-close/instant-close-bulk/instant-close-bulk.js +26 -22
  45. package/dist/solvers/instant-close/instant-close-bulk/instant-close-bulk.js.map +1 -1
  46. package/dist/solvers/instant-close/shared/calldata.d.ts +1 -1
  47. package/dist/solvers/instant-close/shared/calldata.d.ts.map +1 -1
  48. package/dist/solvers/instant-close/shared/calldata.js.map +1 -1
  49. package/dist/solvers/instant-close/shared/resolve-close-order-type.d.ts +13 -0
  50. package/dist/solvers/instant-close/shared/resolve-close-order-type.d.ts.map +1 -0
  51. package/dist/solvers/instant-close/shared/resolve-close-order-type.js +9 -0
  52. package/dist/solvers/instant-close/shared/resolve-close-order-type.js.map +1 -0
  53. package/dist/solvers/instant-close/shared/types.d.ts +3 -3
  54. package/dist/solvers/instant-open/get-instant-open-fees/get-instant-open-fees.d.ts +111 -35
  55. package/dist/solvers/instant-open/get-instant-open-fees/get-instant-open-fees.d.ts.map +1 -1
  56. package/dist/solvers/instant-open/get-instant-open-fees/get-instant-open-fees.js +168 -91
  57. package/dist/solvers/instant-open/get-instant-open-fees/get-instant-open-fees.js.map +1 -1
  58. package/dist/solvers/instant-open/get-instant-open-fees/query.d.ts +3 -2
  59. package/dist/solvers/instant-open/get-instant-open-fees/query.d.ts.map +1 -1
  60. package/dist/solvers/instant-open/get-instant-open-fees/query.js +4 -15
  61. package/dist/solvers/instant-open/get-instant-open-fees/query.js.map +1 -1
  62. package/dist/solvers/instant-open/prepare-instant-open-params/index.d.ts +1 -0
  63. package/dist/solvers/instant-open/prepare-instant-open-params/index.d.ts.map +1 -1
  64. package/dist/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.d.ts +108 -12
  65. package/dist/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.d.ts.map +1 -1
  66. package/dist/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.js +169 -149
  67. package/dist/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.js.map +1 -1
  68. package/dist/solvers/instant-open/prepare-instant-open-params/query.d.ts +49 -0
  69. package/dist/solvers/instant-open/prepare-instant-open-params/query.d.ts.map +1 -0
  70. package/dist/solvers/instant-open/prepare-instant-open-params/query.js +24 -0
  71. package/dist/solvers/instant-open/prepare-instant-open-params/query.js.map +1 -0
  72. package/dist/solvers/instant-open/prepare-instant-open-params/resolvers/index.d.ts +0 -1
  73. package/dist/solvers/instant-open/prepare-instant-open-params/resolvers/index.d.ts.map +1 -1
  74. package/dist/solvers/instant-open/shared/full-balance-sizing.d.ts +164 -0
  75. package/dist/solvers/instant-open/shared/full-balance-sizing.d.ts.map +1 -0
  76. package/dist/solvers/instant-open/shared/full-balance-sizing.js +138 -0
  77. package/dist/solvers/instant-open/shared/full-balance-sizing.js.map +1 -0
  78. package/dist/solvers/instant-open/shared/index.d.ts +1 -0
  79. package/dist/solvers/instant-open/shared/index.d.ts.map +1 -1
  80. package/dist/solvers/instant-open/shared/resolve-instant-open-sizing.d.ts +46 -0
  81. package/dist/solvers/instant-open/shared/resolve-instant-open-sizing.d.ts.map +1 -0
  82. package/dist/solvers/instant-open/shared/resolve-instant-open-sizing.js +50 -0
  83. package/dist/solvers/instant-open/shared/resolve-instant-open-sizing.js.map +1 -0
  84. package/dist/solvers/instant-open/shared/trade-math.d.ts +73 -26
  85. package/dist/solvers/instant-open/shared/trade-math.d.ts.map +1 -1
  86. package/dist/solvers/instant-open/shared/trade-math.js +18 -13
  87. package/dist/solvers/instant-open/shared/trade-math.js.map +1 -1
  88. package/dist/solvers/instant-open/shared/types.d.ts +18 -1
  89. package/dist/solvers/instant-open/shared/types.d.ts.map +1 -1
  90. package/dist/solvers/instant-open/shared/types.js.map +1 -1
  91. package/dist/solvers/limit-open/prepare-limit-open-params.d.ts +3 -1
  92. package/dist/solvers/limit-open/prepare-limit-open-params.d.ts.map +1 -1
  93. package/dist/solvers/limit-open/prepare-limit-open-params.js.map +1 -1
  94. package/dist/solvers/shared/resolvers/index.d.ts +2 -0
  95. package/dist/solvers/shared/resolvers/index.d.ts.map +1 -1
  96. package/dist/solvers/{instant-open/prepare-instant-open-params → shared}/resolvers/resolve-fee-rates.d.ts +3 -3
  97. package/dist/solvers/shared/resolvers/resolve-fee-rates.d.ts.map +1 -0
  98. package/dist/solvers/{instant-open/prepare-instant-open-params → shared}/resolvers/resolve-fee-rates.js +2 -2
  99. package/dist/solvers/shared/resolvers/resolve-fee-rates.js.map +1 -0
  100. package/dist/solvers/shared/resolvers/resolve-market.d.ts +21 -0
  101. package/dist/solvers/shared/resolvers/resolve-market.d.ts.map +1 -1
  102. package/dist/solvers/shared/resolvers/resolve-market.js +34 -18
  103. package/dist/solvers/shared/resolvers/resolve-market.js.map +1 -1
  104. package/dist/solvers/shared/resolvers/resolve-solver-info.d.ts +29 -0
  105. package/dist/solvers/shared/resolvers/resolve-solver-info.d.ts.map +1 -0
  106. package/dist/solvers/shared/resolvers/resolve-solver-info.js +21 -0
  107. package/dist/solvers/shared/resolvers/resolve-solver-info.js.map +1 -0
  108. package/dist/solvers/shared/resolvers/types.d.ts +12 -0
  109. package/dist/solvers/shared/resolvers/types.d.ts.map +1 -1
  110. package/dist/solvers/types/generated/enigma-solver.d.ts +43 -82
  111. package/dist/solvers/types/generated/enigma-solver.d.ts.map +1 -1
  112. package/dist/solvers/types/generated/enigma-solver.js +6 -6
  113. package/dist/solvers/types/generated/enigma-solver.js.map +1 -1
  114. package/dist/symmio-contracts/abi/v0.8.6/account-layer.d.ts +696 -85
  115. package/dist/symmio-contracts/abi/v0.8.6/account-layer.d.ts.map +1 -1
  116. package/dist/symmio-contracts/abi/v0.8.6/account-layer.js +815 -116
  117. package/dist/symmio-contracts/abi/v0.8.6/account-layer.js.map +1 -1
  118. package/dist/symmio-contracts/abi/v0.8.6/symmio.d.ts +1044 -467
  119. package/dist/symmio-contracts/abi/v0.8.6/symmio.d.ts.map +1 -1
  120. package/dist/symmio-contracts/abi/v0.8.6/symmio.js +1183 -496
  121. package/dist/symmio-contracts/abi/v0.8.6/symmio.js.map +1 -1
  122. package/dist/symmio-contracts/symmio/types.d.ts +3 -1
  123. package/dist/symmio-contracts/symmio/types.d.ts.map +1 -1
  124. package/dist/symmio-contracts/symmio/types.js +1 -1
  125. package/dist/symmio-contracts/symmio/types.js.map +1 -1
  126. package/package.json +1 -1
  127. package/dist/solvers/instant-open/prepare-instant-open-params/resolvers/resolve-fee-rates.d.ts.map +0 -1
  128. package/dist/solvers/instant-open/prepare-instant-open-params/resolvers/resolve-fee-rates.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-instant-open-params.js","names":[],"sources":["../../../../src/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.ts"],"sourcesContent":["import type { Address, Hex } from \"viem\";\nimport type { Config } from \"../../../core/config\";\nimport { SymmError } from \"../../../shared/errors/symm-error\";\nimport type { Compute, WriteSolverParameter } from \"../../../shared/types/properties\";\nimport { decimalPriceToWei } from \"../../../shared/utils/price\";\nimport type { FeeForUser } from \"../../../symmio-contracts/symmio/actions/get-fee-for-user\";\nimport type { ApiLockedParamsBySymbolIdResponse } from \"../../types/generated/enigma-solver\";\nimport type { InstantOpenParameters } from \"../instant-open/types\";\nimport {\n assertOpenEstimateWithinSlippage,\n assertValidSlippage,\n deriveAutoSlippage,\n fetchOpenEstimatePrice,\n} from \"../shared/open-estimate-guard\";\nimport {\n calculateExpectedSettlementLoss,\n calculateMargin,\n calculateSolverFees,\n calculateTradeParams,\n computePlatformFee,\n SHORT_FUNDING_BUFFER_PERCENT,\n toWeiBigInt,\n} from \"../shared/trade-math\";\nimport { type InstantOpenMarketData, type PositionType } from \"../shared/types\";\nimport { resolveFeeRates, resolveLockedParams, resolveMarket, resolveMarkPrice } from \"./resolvers\";\n\n/**\n * Default solver-fee rate cap when the market publishes none: `\"0.01\"` — 1% of\n * notional, as a decimal ratio. Applied per side before wei conversion.\n */\nconst DEFAULT_SOLVER_FEE_CAP = \"0.01\";\n\n/**\n * Convert a market's solver-fee cap ratio string to its 18-decimal wei value.\n *\n * An absent cap falls back to {@link DEFAULT_SOLVER_FEE_CAP}; a present but\n * malformed string **throws** rather than silently signing zero caps — the caps\n * are immutable once `sendQuote` lands, so a bad vendor string must surface\n * before the signature, not after.\n *\n * @throws {SymmError} `INVALID_SOLVER_FEE_CAP` when the string does not parse.\n */\nfunction solverFeeCapToWei(field: \"minOpenSolverFeeCap\" | \"minCloseSolverFeeCap\", value: string | undefined): bigint {\n const cap = decimalPriceToWei(value ?? DEFAULT_SOLVER_FEE_CAP);\n if (cap === undefined) {\n throw new SymmError(\n \"validation\",\n \"INVALID_SOLVER_FEE_CAP\",\n `prepareInstantOpenParams: market ${field} \"${value}\" is not a valid decimal ratio.`,\n );\n }\n return cap;\n}\n\n/**\n * Parameters for {@link prepareInstantOpenParams} and `instantOpenAuto`.\n *\n * Required = inputs only the caller can know (wallet, session key, trade\n * intent). Optional = anything derivable from solver / price-service / on-chain\n * reads. Pre-fill an optional field to skip its fetch.\n */\nexport type PrepareInstantOpenParameters = Compute<\n WriteSolverParameter & {\n /** Sub-account / partyA address. */\n subAccountAddress: Address;\n /** Market identification + optional pre-fetched precision metadata. */\n market: InstantOpenMarketData;\n /** Trade side. */\n positionType: PositionType;\n /** Collateral (USD) the user enters as initial margin. Decimal string. */\n initialMargin: string;\n /** Position leverage (integer ≥ 1). */\n leverage: number;\n /**\n * Slippage tolerance percent (e.g. `5` for 5%). **Required on majors\n * (non-lowcap) solvers.** On a lowcap solver it may be omitted to\n * auto-derive: the SDK dry-runs the sized order and sets the price bound\n * to the estimated fill price plus 4% headroom (falling back to a flat 4%\n * off mark when the estimate is unavailable).\n */\n slippage?: number;\n /** Pre-fetched mark price as decimal string. When omitted, fetched via Enigma price service. */\n markPrice?: string;\n /**\n * Pre-fetched solver estimated open (fill) price as decimal string —\n * **lowcap/Enigma only**; ignored on any other solver kind. When omitted\n * on a lowcap solver, fetched via `GET /estimated-price`. Feeds the\n * settlement-loss provision, the slippage gate, and (when `slippage` is\n * omitted) the auto-slippage derivation.\n */\n estimatedOpenPrice?: string;\n /**\n * Pre-fetched solver locked params (matches `getLockedParams` return —\n * `ApiLockedParamsBySymbolIdResponse`). When supplied with all four\n * percent fields, the fetch is skipped.\n */\n lockedParamPercent?: ApiLockedParamsBySymbolIdResponse;\n /**\n * Pre-fetched on-chain fee rates (matches `getFeeForUser` return —\n * `FeeForUser`). When omitted, fetched via `getFeeForUser`.\n */\n feeRates?: FeeForUser;\n /** Forwarded to {@link InstantOpenParameters}. */\n uuid?: string;\n /** Forwarded to {@link InstantOpenParameters}. */\n addMarginSalt?: Hex;\n /** Forwarded to {@link InstantOpenParameters}. */\n sendQuoteSalt?: Hex;\n /** Forwarded to {@link InstantOpenParameters}. */\n deadline?: bigint;\n }\n>;\n\n/**\n * Resolve every input the {@link InstantOpenParameters} primitive needs from a\n * minimal parameter set.\n *\n * The estimate-driven steps (auto slippage, dry-run gate, solver fees,\n * settlement provision) are **lowcap-only** — a majors (non-lowcap) prepare is\n * unchanged: `slippage` required, no estimate fetch, margin = locks +\n * platform fee.\n *\n * Steps:\n * 1. Validate the user's `slippage` ({@link assertValidSlippage}). On a\n * lowcap solver it may be omitted and is auto-derived: dry-run the\n * mark-sized order and set the price bound to the estimated fill plus 4%\n * headroom ({@link deriveAutoSlippage}). On majors an omitted slippage\n * throws `SLIPPAGE_REQUIRED`.\n * 2. Resolve market metadata, mark price, locked params, and fee rates —\n * concurrent fetches with caller-supplied fields short-circuiting.\n * 3. Run {@link calculateTradeParams} to derive `requestedOpenPrice`,\n * `quantity`, `cva`, `lf`, `partyAmm`, `partyBmm`, `notional`.\n * 4. Dry-run the sized order and reject when the expected fill deviates from\n * mark beyond the slippage tolerance\n * ({@link assertOpenEstimateWithinSlippage}; skipped when the estimate is\n * unavailable, reusing the caller-supplied `estimatedOpenPrice` or the\n * auto-slippage estimate when one exists).\n * 5. Run {@link computePlatformFee}, {@link calculateSolverFees}, and\n * {@link calculateExpectedSettlementLoss}, then {@link calculateMargin} to\n * derive the `addMargin` amount — the solver charges its fees and the\n * open-price settlement from the VA, so the transfer funds\n * `locks + platformFee + openSolverFee + closeSolverFee +\n * expectedSettlementLoss`.\n * 6. Convert all final values to 18-decimal-wei `bigint`.\n *\n * @throws {SymmError} `INVALID_SLIPPAGE` / `SLIPPAGE_REQUIRED` /\n * `SLIPPAGE_EXCEEDED` /\n * `RESOLVE_MARKET_NOT_FOUND` /\n * `RESOLVE_MARKET_METADATA_INCOMPLETE` /\n * `RESOLVE_MARK_PRICE_NOT_FOUND` / `INVALID_TRADE_PARAMETERS` /\n * `INVALID_SOLVER_FEE_CAP` for invalid inputs or an out-of-tolerance fill.\n */\nexport async function prepareInstantOpenParams(\n config: Config,\n parameters: PrepareInstantOpenParameters,\n): Promise<InstantOpenParameters> {\n // Reject a malformed user slippage before any network work. An omitted\n // slippage is auto-derived from the dry-run estimate after sizing.\n if (parameters.slippage !== undefined) assertValidSlippage(parameters.slippage);\n\n /**\n * The estimate-driven behaviors — auto slippage, the dry-run gate, solver\n * fees, and the settlement provision — exist only on lowcap (Enigma)\n * solvers. On majors the flow is unchanged: slippage is required, no\n * estimate is fetched, and the margin carries locks + platform fee only.\n */\n const isLowcap = config.getSolver({ chainId: parameters.chainId, solverId: parameters.solverId }).id === \"enigma\";\n if (parameters.slippage === undefined && !isLowcap) {\n throw new SymmError(\n \"validation\",\n \"SLIPPAGE_REQUIRED\",\n \"prepareInstantOpenParams: slippage is required on this solver — auto-derived slippage is lowcap-only.\",\n );\n }\n\n /** Fee caps only exist on the v0.8.6 quote API — don't force a market fetch for them on a legacy chain. */\n const needsSolverFeeCaps = config.getChainConfig(parameters.chainId).contractsVersion === \"0.8.6\";\n\n const market = await resolveMarket(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n marketId: parameters.market.id,\n marketName: parameters.market.name,\n pricePrecision: parameters.market.pricePrecision,\n quantityPrecision: parameters.market.quantityPrecision,\n minOpenSolverFeeCap: parameters.market.minOpenSolverFeeCap,\n minCloseSolverFeeCap: parameters.market.minCloseSolverFeeCap,\n includeSolverFeeCaps: needsSolverFeeCaps,\n hedgerFeeOpen: parameters.market.hedgerFeeOpen,\n hedgerFeeClose: parameters.market.hedgerFeeClose,\n hedgerFeeCloseEarlyRate: parameters.market.hedgerFeeCloseEarlyRate,\n hedgerFeeCloseEarlyThreshold: parameters.market.hedgerFeeCloseEarlyThreshold,\n hedgerFeeCloseStandardThreshold: parameters.market.hedgerFeeCloseStandardThreshold,\n /** Lowcap only: the solver charges its fees from the VA, so `addMargin` must fund them. */\n includeHedgerFees: isLowcap,\n });\n const [markPrice, lockedParams, feeRates] = await Promise.all([\n resolveMarkPrice(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n marketName: market.name,\n markPrice: parameters.markPrice,\n }),\n resolveLockedParams(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n marketName: market.name,\n leverage: parameters.leverage,\n lockedParamPercent: parameters.lockedParamPercent,\n }),\n resolveFeeRates(config, {\n chainId: parameters.chainId,\n subAccountAddress: parameters.subAccountAddress,\n marketId: parameters.market.id,\n feeRates: parameters.feeRates,\n }),\n ]);\n\n const calculationInput = {\n markPrice,\n positionType: parameters.positionType,\n userInput: parameters.initialMargin,\n inputField: \"PRICE\" as const,\n leverage: parameters.leverage,\n pricePrecision: market.pricePrecision,\n quantityPrecision: market.quantityPrecision,\n cvaPercent: lockedParams.cva,\n lfPercent: lockedParams.lf,\n partyAmmPercent: lockedParams.partyAmm,\n partyBmmPercent: lockedParams.partyBmm,\n };\n\n // Auto slippage: dry-run the mark-sized order (quantity is slippage-\n // independent) and set the price bound to the estimated fill plus 4%\n // headroom, re-expressed as a percent off mark. A caller-supplied\n // `estimatedOpenPrice` short-circuits the fetch; either way the estimate is\n // reused by the gate and the settlement provision so the solver is asked at\n // most once.\n let slippage = parameters.slippage;\n let expectedFillPrice = isLowcap ? parameters.estimatedOpenPrice : undefined;\n if (slippage === undefined) {\n const sized = calculateTradeParams({ ...calculationInput, slippage: 0 });\n if (!sized) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"Invalid trade parameters: markPrice or initialMargin is zero/NaN.\",\n );\n }\n if (isLowcap && expectedFillPrice === undefined) {\n expectedFillPrice = await fetchOpenEstimatePrice(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n symbolId: parameters.market.id,\n positionType: parameters.positionType,\n quantity: sized.quantity,\n markPrice,\n });\n }\n slippage = deriveAutoSlippage({ markPrice, expectedFillPrice, positionType: parameters.positionType });\n }\n\n const tradeCalc = calculateTradeParams({ ...calculationInput, slippage });\n if (!tradeCalc) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"Invalid trade parameters: markPrice or initialMargin is zero/NaN.\",\n );\n }\n\n // The expected fill price funds the settlement-loss provision and feeds the\n // slippage gate. Fetch it once here when neither the caller nor the\n // auto-slippage path supplied it — pass `estimatedOpenPrice` to skip the\n // round-trip on latency-sensitive submits.\n if (isLowcap && expectedFillPrice === undefined) {\n expectedFillPrice = await fetchOpenEstimatePrice(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n symbolId: parameters.market.id,\n positionType: parameters.positionType,\n quantity: tradeCalc.quantity,\n markPrice,\n });\n }\n\n // Dry-run gate: reject early when the expected fill deviates from mark\n // beyond the user's slippage — the solver would reject the quote anyway.\n // Best-effort: an unavailable estimate skips the gate, never blocks the open.\n if (expectedFillPrice !== undefined) {\n await assertOpenEstimateWithinSlippage(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n symbolId: parameters.market.id,\n positionType: parameters.positionType,\n quantity: tradeCalc.quantity,\n markPrice,\n slippage,\n expectedFillPrice,\n });\n }\n\n const platformFee = computePlatformFee(feeRates, tradeCalc.notional, tradeCalc.notional);\n // Lowcap: the solver charges its fees and the open-price settlement from the\n // VA balance — the addMargin transfer moves those funds from the SubAccount.\n // Majors carry neither leg; their margin stays locks + platform fee.\n const { openSolverFee, closeSolverFee } = isLowcap\n ? calculateSolverFees({\n notional: tradeCalc.notional,\n hedgerFeeOpen: market.hedgerFeeOpen,\n hedgerFeeClose: market.hedgerFeeClose,\n hedgerFeeCloseEarlyRate: market.hedgerFeeCloseEarlyRate,\n hedgerFeeCloseEarlyThreshold: market.hedgerFeeCloseEarlyThreshold,\n hedgerFeeCloseStandardThreshold: market.hedgerFeeCloseStandardThreshold,\n })\n : { openSolverFee: \"0\", closeSolverFee: \"0\" };\n const expectedSettlementLoss = calculateExpectedSettlementLoss({\n positionType: parameters.positionType,\n markPrice,\n expectedFillPrice,\n quantity: tradeCalc.quantity,\n });\n const marginAmount = calculateMargin({\n positionType: parameters.positionType,\n markPrice,\n quantityBasic: tradeCalc.quantityBasic,\n cva: tradeCalc.cva,\n lf: tradeCalc.lf,\n partyAmm: tradeCalc.partyAmm,\n openSolverFee,\n closeSolverFee,\n expectedSettlementLoss,\n /** Lowcap SHORT: fund lock growth above the floor. Majors keep the classic basis. */\n shortFundingBufferPercent: isLowcap ? SHORT_FUNDING_BUFFER_PERCENT : 0,\n cvaPercent: lockedParams.cva,\n lfPercent: lockedParams.lf,\n partyAmmPercent: lockedParams.partyAmm,\n platformFee,\n });\n\n return {\n chainId: parameters.chainId,\n /**\n * Carried through deliberately: `instantOpen` resolves the solver from it to\n * fill `partyBsWhiteList` — which is signed into the EIP-712 payload — and to\n * pick the submit URL. Dropping it here would sign against the default\n * solver's address while the quote was priced and sized for another.\n */\n solverId: parameters.solverId,\n from: parameters.from,\n subAccountAddress: parameters.subAccountAddress,\n marketId: parameters.market.id,\n positionType: parameters.positionType,\n order: {\n price: toWeiBigInt(tradeCalc.requestedOpenPrice),\n quantity: toWeiBigInt(tradeCalc.quantity),\n },\n lockedParam: {\n cva: toWeiBigInt(tradeCalc.cva),\n lf: toWeiBigInt(tradeCalc.lf),\n partyAmm: toWeiBigInt(tradeCalc.partyAmm),\n partyBmm: toWeiBigInt(tradeCalc.partyBmm),\n },\n margin: {\n amount: toWeiBigInt(marginAmount),\n },\n /** Only meaningful on a v0.8.6 chain — absent on v0.8.5, whose flow signs the legacy call. */\n ...(needsSolverFeeCaps\n ? {\n solverFeeCaps: {\n openRateCap: solverFeeCapToWei(\"minOpenSolverFeeCap\", market.minOpenSolverFeeCap),\n closeRateCap: solverFeeCapToWei(\"minCloseSolverFeeCap\", market.minCloseSolverFeeCap),\n },\n }\n : {}),\n uuid: parameters.uuid,\n addMarginSalt: parameters.addMarginSalt,\n sendQuoteSalt: parameters.sendQuoteSalt,\n deadline: parameters.deadline,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prepare-instant-open-params.js","names":[],"sources":["../../../../src/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.ts"],"sourcesContent":["import { RoundingMode, toDecimal } from \"@symmio/utils/decimal\";\nimport { parseUnits, type Address, type Hex } from \"viem\";\nimport type { Config } from \"../../../core/config\";\nimport { SymmError } from \"../../../shared/errors/symm-error\";\nimport type { Compute, WriteSolverParameter } from \"../../../shared/types/properties\";\nimport { decimalPriceToWei } from \"../../../shared/utils/price\";\nimport type { FeeForUser } from \"../../../symmio-contracts/symmio/actions/get-fee-for-user\";\nimport type { EnigmaSolverInfo } from \"../../get-solver-info\";\nimport type { ApiLockedParamsBySymbolIdResponse } from \"../../types/generated/enigma-solver\";\nimport type { InstantOpenParameters } from \"../instant-open/types\";\nimport {\n assertOpenEstimateWithinSlippage,\n assertValidSlippage,\n deriveAutoSlippage,\n fetchOpenEstimatePrice,\n} from \"../shared/open-estimate-guard\";\nimport { resolveInstantOpenSizing, validateInstantOpenBalanceFunding } from \"../shared/resolve-instant-open-sizing\";\nimport { calculateTradeParams, toWeiBigInt } from \"../shared/trade-math\";\nimport { type InstantOpenMarketData, type PositionType } from \"../shared/types\";\nimport { resolveFeeRates, resolveLockedParams, resolveMarket, resolveMarkPrice, resolveSolverInfo } from \"./resolvers\";\n\n/**\n * Default solver-fee rate cap when the market publishes none: `\"0.01\"` — 1% of\n * notional, as a decimal ratio. Applied per side before wei conversion.\n */\nconst DEFAULT_SOLVER_FEE_CAP = \"0.01\";\n\n/**\n * Convert a market's solver-fee cap ratio string to its 18-decimal wei value.\n *\n * An absent cap falls back to {@link DEFAULT_SOLVER_FEE_CAP}; a present but\n * malformed string **throws** rather than silently signing zero caps — the caps\n * are immutable once `sendQuote` lands, so a bad vendor string must surface\n * before the signature, not after.\n *\n * @throws {SymmError} `INVALID_SOLVER_FEE_CAP` when the string does not parse.\n */\nfunction solverFeeCapToWei(field: \"minOpenSolverFeeCap\" | \"minCloseSolverFeeCap\", value: string | undefined): bigint {\n const cap = decimalPriceToWei(value ?? DEFAULT_SOLVER_FEE_CAP);\n if (cap === undefined) {\n throw new SymmError(\n \"validation\",\n \"INVALID_SOLVER_FEE_CAP\",\n `prepareInstantOpenParams: market ${field} \"${value}\" is not a valid decimal ratio.`,\n );\n }\n return cap;\n}\n\n/**\n * Parameters for {@link prepareInstantOpenParams} and `instantOpenAuto`.\n *\n * Required = inputs only the caller can know (wallet, session key, trade\n * intent). Optional = anything derivable from solver / price-service / on-chain\n * reads. Pre-fill an optional field to skip its fetch.\n */\n/**\n * Full-balance funding for a lowcap (Enigma) open — deploy the **entire**\n * selected collateral into the position's Virtual Account instead of typing an\n * initial margin.\n *\n * With a typed `initialMargin` the SubAccount keeps back whatever the position\n * did not need (locks + open fees + settlement), so a user who deposited `$100`\n * and hit \"Max\" saw a smaller spendable figure and left dust behind. In this\n * mode the whole balance moves to the VA and the SDK sizes the quantity **down**\n * so its locks + open fees + worst-case settlement fit inside it — nothing is\n * stranded and the figure the user deployed is the figure they picked. (Close\n * fees are charged at close from the position, so they are not sized in here.)\n *\n * Lowcap (Enigma) only: it relies on the per-position VA and the solver-fee /\n * settlement legs a majors (cross-margin) open does not have.\n */\nexport interface FullBalanceFunding {\n /** Discriminant selecting the full-balance sizing path. */\n mode: \"full-balance\";\n /** The entire collateral to move into the VA, as a USD decimal string. */\n balance: string;\n}\n\n/**\n * Fields shared by every {@link PrepareInstantOpenParameters} funding mode.\n */\ntype PrepareInstantOpenBaseParameters = WriteSolverParameter & {\n /** Sub-account / partyA address. */\n subAccountAddress: Address;\n /** Market identification + optional pre-fetched precision metadata. */\n market: InstantOpenMarketData;\n /** Trade side. */\n positionType: PositionType;\n /** Position leverage (integer ≥ 1). */\n leverage: number;\n /**\n * Slippage tolerance percent (e.g. `5` for 5%). **Required on majors\n * (non-lowcap) solvers.** On a lowcap solver it may be omitted to\n * auto-derive: the SDK dry-runs the sized order and sets the price bound\n * to the estimated fill price plus 4% headroom (falling back to a flat 4%\n * off mark when the estimate is unavailable).\n */\n slippage?: number;\n /** Pre-fetched mark price as decimal string. When omitted, fetched via Enigma price service. */\n markPrice?: string;\n /**\n * Pre-fetched solver estimated open (fill) price as decimal string —\n * **lowcap/Enigma only**; ignored on any other solver kind. When omitted\n * on a lowcap solver, fetched via `GET /estimated-price`. Pass `null` when\n * an estimate was attempted but unavailable to skip fetching and use the fallback.\n * Feeds the settlement-loss provision, the slippage gate, and (when `slippage` is\n * omitted) the auto-slippage derivation.\n */\n estimatedOpenPrice?: string | null;\n /**\n * Pre-fetched solver locked params (matches `getLockedParams` return —\n * `ApiLockedParamsBySymbolIdResponse`). When supplied with all four\n * percent fields, the fetch is skipped.\n */\n lockedParamPercent?: ApiLockedParamsBySymbolIdResponse;\n /**\n * Pre-fetched on-chain fee rates (matches `getFeeForUser` return —\n * `FeeForUser`). When omitted, fetched via `getFeeForUser`.\n */\n feeRates?: FeeForUser;\n /**\n * Pre-fetched solver static fees (matches `getSolverInfo` return) —\n * **lowcap/Enigma only**; ignored on any other solver kind. When omitted on\n * a lowcap solver, fetched via `getSolverInfo` (fail-soft: an unreachable\n * `/info` prices both static legs at `\"0\"`). The flat USD legs ride the\n * `addMargin` transfer like the rate-based solver fees.\n */\n solverInfo?: EnigmaSolverInfo;\n /** Forwarded to {@link InstantOpenParameters}. */\n uuid?: string;\n /** Forwarded to {@link InstantOpenParameters}. */\n addMarginSalt?: Hex;\n /** Forwarded to {@link InstantOpenParameters}. */\n sendQuoteSalt?: Hex;\n /** Forwarded to {@link InstantOpenParameters}. */\n deadline?: bigint;\n};\n\n/**\n * Parameters for {@link prepareInstantOpenParams} and `instantOpenAuto`.\n *\n * The funding source is a choice: pass a typed `initialMargin` (the classic\n * path, works on every solver), **or** `fund` with {@link FullBalanceFunding} to\n * deploy the whole balance on a lowcap (Enigma) solver. Provide **exactly one** —\n * passing both, or neither, throws. (Both are typed optional so the params\n * spread cleanly through wrapper flows; the one-of rule is enforced at runtime.)\n */\nexport type PrepareInstantOpenParameters = Compute<\n PrepareInstantOpenBaseParameters & {\n /** Collateral (USD) the user enters as initial margin. Decimal string. Provide this **or** `fund`. */\n initialMargin?: string;\n /**\n * Raw available collateral (USD decimal string). With initialMargin, automatically\n * use full-balance sizing when required funding exceeds this amount. Lowcap only;\n * must be positive and finite. initialMargin above this balance throws.\n * Omit to preserve typed sizing. Cannot accompany fund.\n */\n availableBalance?: string;\n /**\n * Deploy the entire collateral and size the quantity to fit it — lowcap\n * (Enigma) only. Provide this **or** `initialMargin`. See\n * {@link FullBalanceFunding}.\n */\n fund?: FullBalanceFunding;\n }\n>;\n\n/** Prepared order parameters plus the effective funding mode. Pass directly to instantOpen. */\nexport type PrepareInstantOpenParamsReturnType = InstantOpenParameters & {\n /** Effective sizing mode, including automatic fallback from a typed initial margin. */\n fundingMode: \"initial-margin\" | \"full-balance\";\n};\n\n/**\n * Resolve every input the {@link InstantOpenParameters} primitive needs from a\n * minimal parameter set.\n *\n * The estimate-driven steps (auto slippage, dry-run gate, solver fees,\n * settlement provision) are **lowcap-only** — a majors (non-lowcap) prepare is\n * unchanged: `slippage` required, no estimate fetch, margin = locks +\n * platform fee.\n *\n * Funding is a discriminated choice (see {@link PrepareInstantOpenParameters}):\n * a typed `initialMargin`, or `fund` ({@link FullBalanceFunding}, lowcap only)\n * to deploy the whole balance. In full-balance mode the balance is used as a\n * sizing probe: since the addMargin amount is linear in the sizing input at a\n * fixed fill price, one probe gives the exact factor that shrinks the quantity\n * so its locks + fees + settlement fit the balance, and the transfer then funds\n * the whole balance (any remainder rides as free VA margin). The sized\n * quantity is snapped down to the market's lot grid, re-checked so its costs\n * never exceed the balance (precision rounding can overshoot the linear\n * factor), and validated against the market's published quote constraints;\n * when no fill estimate is available the settlement leg is provisioned at the\n * slippage bound instead of zero — a full-balance open leaves nothing behind\n * to absorb an optimistic estimate.\n *\n * Pass `availableBalance` with `initialMargin` to automatically select full-balance\n * sizing when the typed position's required funding exceeds the raw balance.\n * An initialMargin above availableBalance throws before sizing. Otherwise, funding\n * equality preserves typed sizing. The returned `fundingMode` reports the choice.\n *\n * @param config - SDK configuration used to resolve market and account inputs.\n * @param parameters - Trade intent, optional balance budget, and prefetched inputs.\n * @returns Prepared order parameters and the effective funding mode.\n *\n * Steps:\n * 1. Validate the user's `slippage` ({@link assertValidSlippage}). On a\n * lowcap solver it may be omitted and is auto-derived: dry-run the\n * mark-sized order and set the price bound to the estimated fill plus 4%\n * headroom ({@link deriveAutoSlippage}). On majors an omitted slippage\n * throws `SLIPPAGE_REQUIRED`.\n * 2. Resolve market metadata, mark price, locked params, and fee rates —\n * concurrent fetches with caller-supplied fields short-circuiting.\n * 3. Run {@link calculateTradeParams} to derive `requestedOpenPrice`,\n * `quantity`, `cva`, `lf`, `partyAmm`, `partyBmm`, `notional`.\n * 4. Dry-run the sized order and reject when the expected fill deviates from\n * mark beyond the slippage tolerance\n * ({@link assertOpenEstimateWithinSlippage}; skipped when the estimate is\n * unavailable, reusing the caller-supplied `estimatedOpenPrice` or the\n * auto-slippage estimate when one exists).\n * 5. Run {@link computePlatformFee}, {@link calculateSolverFees}, and\n * {@link calculateExpectedSettlementLoss}, then {@link calculateMargin} to\n * derive the `addMargin` amount. The open funds only the **open-side** legs\n * plus the open-price settlement from the VA, so the transfer funds\n * `locks + platformOpenFee + openSolverFee + staticSolverFeeOpen +\n * expectedSettlementLoss` (the static open leg is a flat USD amount from the\n * solver's `/info` config). The close-side legs (platform close, solver\n * close, static close) are **charged at close** from the position — the\n * contract collects them at close execution — so they are not pre-funded\n * here; pre-funding them would strand collateral in the VA. In full-balance\n * mode the quantity is rescaled to fit the balance — the static open leg is\n * carved off the budget before the linear solve — and the `addMargin` amount\n * is the whole balance instead.\n * 6. Convert all final values to 18-decimal-wei `bigint`.\n *\n * @throws {SymmError} `INVALID_SLIPPAGE` / `SLIPPAGE_REQUIRED` /\n * `SLIPPAGE_EXCEEDED` / `AMBIGUOUS_FUNDING` / `FULL_BALANCE_UNSUPPORTED` /\n * `INITIAL_MARGIN_REQUIRED` / `QUOTE_CONSTRAINT_VIOLATED` /\n * `RESOLVE_MARKET_NOT_FOUND` /\n * `RESOLVE_MARKET_METADATA_INCOMPLETE` /\n * `RESOLVE_MARK_PRICE_NOT_FOUND` / `INVALID_TRADE_PARAMETERS` /\n * `INVALID_SOLVER_FEE_CAP` for invalid inputs or an out-of-tolerance fill.\n */\nexport async function prepareInstantOpenParams(\n config: Config,\n parameters: PrepareInstantOpenParameters,\n): Promise<PrepareInstantOpenParamsReturnType> {\n // Reject a malformed user slippage before any network work. An omitted\n // slippage is auto-derived from the dry-run estimate after sizing.\n if (parameters.slippage !== undefined) assertValidSlippage(parameters.slippage);\n\n /**\n * The estimate-driven behaviors — auto slippage, the dry-run gate, solver\n * fees, and the settlement provision — exist only on lowcap (Enigma)\n * solvers. On majors the flow is unchanged: slippage is required, no\n * estimate is fetched, and the margin carries locks + the platform open fee\n * only (the platform close fee is charged at close).\n */\n const isLowcap = config.getSolver({ chainId: parameters.chainId, solverId: parameters.solverId }).id === \"enigma\";\n if (parameters.slippage === undefined && !isLowcap) {\n throw new SymmError(\n \"validation\",\n \"SLIPPAGE_REQUIRED\",\n \"prepareInstantOpenParams: slippage is required on this solver — auto-derived slippage is lowcap-only.\",\n );\n }\n\n // Full-balance funding relies on the per-position VA plus the solver-fee and\n // settlement legs a majors open does not carry, so it is lowcap-only. When it\n // is off, a typed initialMargin is mandatory (the union guarantees this for TS\n // callers; this guard covers plain-JS ones).\n const isFullBalance = parameters.fund !== undefined;\n validateInstantOpenBalanceFunding({ ...parameters, isLowcap });\n const canSizeFullBalance = isFullBalance || parameters.availableBalance !== undefined;\n if (isFullBalance && parameters.initialMargin !== undefined) {\n throw new SymmError(\n \"validation\",\n \"AMBIGUOUS_FUNDING\",\n \"prepareInstantOpenParams: pass exactly one of initialMargin or fund, not both.\",\n );\n }\n if (isFullBalance && !isLowcap) {\n throw new SymmError(\n \"validation\",\n \"FULL_BALANCE_UNSUPPORTED\",\n \"prepareInstantOpenParams: full-balance funding is lowcap (Enigma) only — pass initialMargin on this solver.\",\n );\n }\n if (!isFullBalance && parameters.initialMargin === undefined) {\n throw new SymmError(\n \"validation\",\n \"INITIAL_MARGIN_REQUIRED\",\n \"prepareInstantOpenParams: pass initialMargin, or fund: { mode: 'full-balance', balance } on a lowcap solver.\",\n );\n }\n // The sizing input: the typed margin, or — in full-balance mode — the whole\n // balance used as a probe. The final quantity is rescaled from it below.\n const initialMargin = isFullBalance ? parameters.fund!.balance : parameters.initialMargin!;\n\n /** Fee caps only exist on the v0.8.6 quote API — don't force a market fetch for them on a legacy chain. */\n const needsSolverFeeCaps = config.getChainConfig(parameters.chainId).contractsVersion === \"0.8.6\";\n\n const market = await resolveMarket(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n marketId: parameters.market.id,\n marketName: parameters.market.name,\n pricePrecision: parameters.market.pricePrecision,\n quantityPrecision: parameters.market.quantityPrecision,\n minOpenSolverFeeCap: parameters.market.minOpenSolverFeeCap,\n minCloseSolverFeeCap: parameters.market.minCloseSolverFeeCap,\n includeSolverFeeCaps: needsSolverFeeCaps,\n hedgerFeeOpen: parameters.market.hedgerFeeOpen,\n hedgerFeeClose: parameters.market.hedgerFeeClose,\n hedgerFeeCloseEarlyRate: parameters.market.hedgerFeeCloseEarlyRate,\n hedgerFeeCloseEarlyThreshold: parameters.market.hedgerFeeCloseEarlyThreshold,\n hedgerFeeCloseStandardThreshold: parameters.market.hedgerFeeCloseStandardThreshold,\n /** Lowcap only: the solver charges its fees from the VA, so `addMargin` must fund them. */\n includeHedgerFees: isLowcap,\n /** Explicit or automatic full-balance sizing needs the lot grid and published floors. */\n includeQuoteConstraints: canSizeFullBalance,\n minAcceptablePortionLf: parameters.market.minAcceptablePortionLf,\n minAcceptableQuoteValue: parameters.market.minAcceptableQuoteValue,\n maxNotionalValue: parameters.market.maxNotionalValue,\n minNotionalValue: parameters.market.minNotionalValue,\n maxQuantity: parameters.market.maxQuantity,\n lotSize: parameters.market.lotSize,\n });\n const [markPrice, lockedParams, feeRates, staticFees] = await Promise.all([\n resolveMarkPrice(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n marketName: market.name,\n markPrice: parameters.markPrice,\n }),\n resolveLockedParams(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n marketName: market.name,\n leverage: parameters.leverage,\n lockedParamPercent: parameters.lockedParamPercent,\n }),\n resolveFeeRates(config, {\n chainId: parameters.chainId,\n subAccountAddress: parameters.subAccountAddress,\n marketId: parameters.market.id,\n feeRates: parameters.feeRates,\n }),\n // Static solver fees are a lowcap leg — a majors open never fetches them.\n isLowcap\n ? resolveSolverInfo(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n solverInfo: parameters.solverInfo,\n })\n : Promise.resolve({ staticSolverFeeOpen: \"0\", staticSolverFeeClose: \"0\" }),\n ]);\n\n const calculationInput = {\n markPrice,\n positionType: parameters.positionType,\n userInput: initialMargin,\n inputField: \"PRICE\" as const,\n leverage: parameters.leverage,\n pricePrecision: market.pricePrecision,\n quantityPrecision: market.quantityPrecision,\n cvaPercent: lockedParams.cva,\n lfPercent: lockedParams.lf,\n partyAmmPercent: lockedParams.partyAmm,\n partyBmmPercent: lockedParams.partyBmm,\n };\n\n // Auto slippage: dry-run the mark-sized order (quantity is slippage-\n // independent) and set the price bound to the estimated fill plus 4%\n // headroom, re-expressed as a percent off mark. A caller-supplied\n // `estimatedOpenPrice` short-circuits the fetch; either way the estimate is\n // reused by the gate and the settlement provision so the solver is asked at\n // most once.\n let slippage = parameters.slippage;\n let expectedFillPrice = isLowcap ? (parameters.estimatedOpenPrice ?? undefined) : undefined;\n let needsEstimate = isLowcap && parameters.estimatedOpenPrice === undefined;\n if (slippage === undefined) {\n const sized = calculateTradeParams({ ...calculationInput, slippage: 0 });\n if (!sized) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"Invalid trade parameters: markPrice or initialMargin is zero/NaN.\",\n );\n }\n if (needsEstimate) {\n needsEstimate = false;\n expectedFillPrice = await fetchOpenEstimatePrice(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n symbolId: parameters.market.id,\n positionType: parameters.positionType,\n quantity: sized.quantity,\n markPrice,\n });\n }\n slippage = deriveAutoSlippage({ markPrice, expectedFillPrice, positionType: parameters.positionType });\n }\n\n const tradeCalc = calculateTradeParams({ ...calculationInput, slippage });\n if (!tradeCalc) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"Invalid trade parameters: markPrice or initialMargin is zero/NaN.\",\n );\n }\n\n // The expected fill price funds the settlement-loss provision and feeds the\n // slippage gate. Fetch it once here when neither the caller nor the\n // auto-slippage path supplied it — pass `estimatedOpenPrice` to skip the\n // round-trip on latency-sensitive submits.\n if (needsEstimate) {\n expectedFillPrice = await fetchOpenEstimatePrice(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n symbolId: parameters.market.id,\n positionType: parameters.positionType,\n quantity: tradeCalc.quantity,\n markPrice,\n });\n }\n\n // Dry-run gate: reject early when the expected fill deviates from mark\n // beyond the user's slippage — the solver would reject the quote anyway.\n // Best-effort: an unavailable estimate skips the gate, never blocks the open.\n if (expectedFillPrice !== undefined) {\n await assertOpenEstimateWithinSlippage(config, {\n chainId: parameters.chainId,\n solverId: parameters.solverId,\n symbolId: parameters.market.id,\n positionType: parameters.positionType,\n quantity: tradeCalc.quantity,\n markPrice,\n slippage,\n expectedFillPrice,\n });\n }\n\n // The cost legs a sized order pays. The open funds the OPEN-side legs and the\n // open-price settlement from the VA (they ride the SubAccount → VA transfer);\n // the close-side legs are charged at close from the position, not funded here.\n // Majors carry locks + the platform open fee only. The shared cost model\n // (`computeInstantOpenCosts`) is also what `getInstantOpenFees` prices, so the\n // preview equals what the open charges by construction.\n const {\n trade: finalTrade,\n marginAmount,\n fundingMode,\n } = resolveInstantOpenSizing({\n trade: tradeCalc,\n calculationInput: { ...calculationInput, slippage },\n isLowcap,\n fund: parameters.fund,\n availableBalance: parameters.availableBalance,\n expectedFillPrice,\n feeRates,\n hedgerFeeOpen: market.hedgerFeeOpen,\n staticSolverFeeOpen: staticFees.staticSolverFeeOpen,\n constraints: {\n minAcceptablePortionLf: market.minAcceptablePortionLf,\n minAcceptableQuoteValue: market.minAcceptableQuoteValue,\n maxNotionalValue: market.maxNotionalValue,\n minNotionalValue: market.minNotionalValue,\n maxQuantity: market.maxQuantity,\n lotSize: market.lotSize,\n },\n });\n\n return {\n fundingMode,\n chainId: parameters.chainId,\n /**\n * Carried through deliberately: `instantOpen` resolves the solver from it to\n * fill `partyBsWhiteList` — which is signed into the EIP-712 payload — and to\n * pick the submit URL. Dropping it here would sign against the default\n * solver's address while the quote was priced and sized for another.\n */\n solverId: parameters.solverId,\n from: parameters.from,\n subAccountAddress: parameters.subAccountAddress,\n marketId: parameters.market.id,\n positionType: parameters.positionType,\n order: {\n price: toWeiBigInt(finalTrade.requestedOpenPrice),\n quantity: toWeiBigInt(finalTrade.quantity),\n },\n lockedParam: {\n cva: toWeiBigInt(finalTrade.cva),\n lf: toWeiBigInt(finalTrade.lf),\n partyAmm: toWeiBigInt(finalTrade.partyAmm),\n partyBmm: toWeiBigInt(finalTrade.partyBmm),\n },\n margin: {\n // Shift the decimal point without a Decimal multiplication, whose global\n // significant-digit precision can round a full balance up by one wei.\n amount: parseUnits(toDecimal(marginAmount).toFixed(18, RoundingMode.ROUND_DOWN), 18),\n },\n /** Only meaningful on a v0.8.6 chain — absent on v0.8.5, whose flow signs the legacy call. */\n ...(needsSolverFeeCaps\n ? {\n solverFeeCaps: {\n openRateCap: solverFeeCapToWei(\"minOpenSolverFeeCap\", market.minOpenSolverFeeCap),\n closeRateCap: solverFeeCapToWei(\"minCloseSolverFeeCap\", market.minCloseSolverFeeCap),\n },\n }\n : {}),\n uuid: parameters.uuid,\n addMarginSalt: parameters.addMarginSalt,\n sendQuoteSalt: parameters.sendQuoteSalt,\n deadline: parameters.deadline,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { Config } from '../../../core/config/index.js';
2
+ import { Compute, ConfigKeyParameter } from '../../../shared/types/properties.js';
3
+ import { QueryParameter, SymmioQueryOptions } from '../../../shared/types/query.js';
4
+ import { PrepareInstantOpenParameters, PrepareInstantOpenParamsReturnType } from './prepare-instant-open-params.js';
5
+ /** Data resolved by the {@link prepareInstantOpenParamsQueryOptions} query — the exact params a send will sign. */
6
+ export type PrepareInstantOpenParamsData = PrepareInstantOpenParamsReturnType;
7
+ /** Build the TanStack Query key for {@link prepareInstantOpenParamsQueryOptions}. */
8
+ export declare function getPrepareInstantOpenParamsQueryKey(options: Compute<PrepareInstantOpenParameters & ConfigKeyParameter>): readonly ["prepareInstantOpenParams", Record<string, unknown>];
9
+ /** Query-key type produced by {@link getPrepareInstantOpenParamsQueryKey}. */
10
+ export type PrepareInstantOpenParamsQueryKey = ReturnType<typeof getPrepareInstantOpenParamsQueryKey>;
11
+ /** Options accepted by {@link prepareInstantOpenParamsQueryOptions}. */
12
+ export type PrepareInstantOpenParamsOptions = Compute<PrepareInstantOpenParameters & QueryParameter<PrepareInstantOpenParamsData, Error, PrepareInstantOpenParamsData, PrepareInstantOpenParamsQueryKey>>;
13
+ /** TanStack Query options returned by {@link prepareInstantOpenParamsQueryOptions}. */
14
+ export type PrepareInstantOpenParamsQueryOptions = SymmioQueryOptions<PrepareInstantOpenParamsData, Error, PrepareInstantOpenParamsData, PrepareInstantOpenParamsQueryKey>;
15
+ /**
16
+ * Build TanStack Query options for {@link prepareInstantOpenParams} — a
17
+ * **read-only preview** of the exact {@link InstantOpenParameters} a send will
18
+ * sign. `prepareInstantOpenParams` neither signs nor submits, so this is safe to
19
+ * run live as inputs change; feed the result straight into a "quote preview" so
20
+ * what the user sees is bit-for-bit what `sendQuote` receives.
21
+ *
22
+ * Disabled until a funding source exists — a non-empty `initialMargin`, or a
23
+ * `fund` with a balance. Pre-fill the optional fields (`markPrice`, `feeRates`,
24
+ * `lockedParamPercent`, `estimatedOpenPrice`, market metadata) so the query
25
+ * function is pure and does no per-render network; passing the same
26
+ * `estimatedOpenPrice` here and to the submit makes `margin.amount` (whose
27
+ * settlement leg tracks the estimate) match the sent quote exactly.
28
+ *
29
+ * The slippage gate inside `prepareInstantOpenParams` still runs, so an
30
+ * out-of-tolerance estimate surfaces as the query error — the honest preview of
31
+ * a quote the submit would also reject.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * useQuery(
36
+ * prepareInstantOpenParamsQueryOptions(config, {
37
+ * subAccountAddress,
38
+ * from: sessionKey,
39
+ * market: { id: 1 },
40
+ * positionType: PositionType.LONG,
41
+ * initialMargin: "100",
42
+ * leverage: 5,
43
+ * slippage: 1,
44
+ * }),
45
+ * );
46
+ * ```
47
+ */
48
+ export declare function prepareInstantOpenParamsQueryOptions(config: Config, options: PrepareInstantOpenParamsOptions): PrepareInstantOpenParamsQueryOptions;
49
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/prepare-instant-open-params/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEtF,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACxC,MAAM,+BAA+B,CAAC;AAEvC,mHAAmH;AACnH,MAAM,MAAM,4BAA4B,GAAG,kCAAkC,CAAC;AAE9E,qFAAqF;AACrF,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,OAAO,CAAC,4BAA4B,GAAG,kBAAkB,CAAC,kEAGpE;AAED,8EAA8E;AAC9E,MAAM,MAAM,gCAAgC,GAAG,UAAU,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEtG,wEAAwE;AACxE,MAAM,MAAM,+BAA+B,GAAG,OAAO,CACnD,4BAA4B,GAC1B,cAAc,CAAC,4BAA4B,EAAE,KAAK,EAAE,4BAA4B,EAAE,gCAAgC,CAAC,CACtH,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,oCAAoC,GAAG,kBAAkB,CACnE,4BAA4B,EAC5B,KAAK,EACL,4BAA4B,EAC5B,gCAAgC,CACjC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,+BAA+B,GACvC,oCAAoC,CAiBtC"}
@@ -0,0 +1,24 @@
1
+ import { filterQueryOptions as e } from "../../../shared/utils/query.js";
2
+ import { prepareInstantOpenParams as t } from "./prepare-instant-open-params.js";
3
+ //#region src/solvers/instant-open/prepare-instant-open-params/query.ts
4
+ function n(t) {
5
+ return ["prepareInstantOpenParams", e(t)];
6
+ }
7
+ function r(e, r) {
8
+ let i = { ...r };
9
+ delete i.query;
10
+ let a = i.fund === void 0 ? (i.initialMargin?.length ?? 0) > 0 : i.fund.balance.length > 0;
11
+ return {
12
+ ...r.query,
13
+ queryKey: n({
14
+ ...r,
15
+ configKey: e.getChainConfigKey(r.chainId)
16
+ }),
17
+ enabled: (r.query?.enabled ?? !0) && a,
18
+ queryFn: () => t(e, i)
19
+ };
20
+ }
21
+ //#endregion
22
+ export { n as getPrepareInstantOpenParamsQueryKey, r as prepareInstantOpenParamsQueryOptions };
23
+
24
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","names":[],"sources":["../../../../src/solvers/instant-open/prepare-instant-open-params/query.ts"],"sourcesContent":["import type { Config } from \"../../../core/config\";\nimport type { Compute, ConfigKeyParameter } from \"../../../shared/types/properties\";\nimport type { QueryParameter, SymmioQueryOptions } from \"../../../shared/types/query\";\nimport { filterQueryOptions } from \"../../../shared/utils/query\";\nimport {\n prepareInstantOpenParams,\n type PrepareInstantOpenParameters,\n type PrepareInstantOpenParamsReturnType,\n} from \"./prepare-instant-open-params\";\n\n/** Data resolved by the {@link prepareInstantOpenParamsQueryOptions} query — the exact params a send will sign. */\nexport type PrepareInstantOpenParamsData = PrepareInstantOpenParamsReturnType;\n\n/** Build the TanStack Query key for {@link prepareInstantOpenParamsQueryOptions}. */\nexport function getPrepareInstantOpenParamsQueryKey(\n options: Compute<PrepareInstantOpenParameters & ConfigKeyParameter>,\n) {\n return [\"prepareInstantOpenParams\", filterQueryOptions(options)] as const;\n}\n\n/** Query-key type produced by {@link getPrepareInstantOpenParamsQueryKey}. */\nexport type PrepareInstantOpenParamsQueryKey = ReturnType<typeof getPrepareInstantOpenParamsQueryKey>;\n\n/** Options accepted by {@link prepareInstantOpenParamsQueryOptions}. */\nexport type PrepareInstantOpenParamsOptions = Compute<\n PrepareInstantOpenParameters &\n QueryParameter<PrepareInstantOpenParamsData, Error, PrepareInstantOpenParamsData, PrepareInstantOpenParamsQueryKey>\n>;\n\n/** TanStack Query options returned by {@link prepareInstantOpenParamsQueryOptions}. */\nexport type PrepareInstantOpenParamsQueryOptions = SymmioQueryOptions<\n PrepareInstantOpenParamsData,\n Error,\n PrepareInstantOpenParamsData,\n PrepareInstantOpenParamsQueryKey\n>;\n\n/**\n * Build TanStack Query options for {@link prepareInstantOpenParams} — a\n * **read-only preview** of the exact {@link InstantOpenParameters} a send will\n * sign. `prepareInstantOpenParams` neither signs nor submits, so this is safe to\n * run live as inputs change; feed the result straight into a \"quote preview\" so\n * what the user sees is bit-for-bit what `sendQuote` receives.\n *\n * Disabled until a funding source exists — a non-empty `initialMargin`, or a\n * `fund` with a balance. Pre-fill the optional fields (`markPrice`, `feeRates`,\n * `lockedParamPercent`, `estimatedOpenPrice`, market metadata) so the query\n * function is pure and does no per-render network; passing the same\n * `estimatedOpenPrice` here and to the submit makes `margin.amount` (whose\n * settlement leg tracks the estimate) match the sent quote exactly.\n *\n * The slippage gate inside `prepareInstantOpenParams` still runs, so an\n * out-of-tolerance estimate surfaces as the query error — the honest preview of\n * a quote the submit would also reject.\n *\n * @example\n * ```ts\n * useQuery(\n * prepareInstantOpenParamsQueryOptions(config, {\n * subAccountAddress,\n * from: sessionKey,\n * market: { id: 1 },\n * positionType: PositionType.LONG,\n * initialMargin: \"100\",\n * leverage: 5,\n * slippage: 1,\n * }),\n * );\n * ```\n */\nexport function prepareInstantOpenParamsQueryOptions(\n config: Config,\n options: PrepareInstantOpenParamsOptions,\n): PrepareInstantOpenParamsQueryOptions {\n // Strip the TanStack `query` bag before the SDK call — spreading it into\n // `prepareInstantOpenParams` would leak UI options into the wizard. A copy +\n // delete (instead of naming every field) keeps future params flowing through.\n const parameters: PrepareInstantOpenParamsOptions = { ...options };\n delete parameters.query;\n const hasFunding =\n parameters.fund !== undefined ? parameters.fund.balance.length > 0 : (parameters.initialMargin?.length ?? 0) > 0;\n return {\n ...options.query,\n queryKey: getPrepareInstantOpenParamsQueryKey({\n ...options,\n configKey: config.getChainConfigKey(options.chainId),\n }),\n enabled: (options.query?.enabled ?? true) && hasFunding,\n queryFn: () => prepareInstantOpenParams(config, parameters),\n };\n}\n"],"mappings":";;;AAcA,SAAgB,EACd,GACA;CACA,OAAO,CAAC,4BAA4B,EAAmB,CAAO,CAAC;AACjE;AAoDA,SAAgB,EACd,GACA,GACsC;CAItC,IAAM,IAA8C,EAAE,GAAG,EAAQ;CACjE,OAAO,EAAW;CAClB,IAAM,IACJ,EAAW,SAAS,KAAA,KAAkD,EAAW,eAAe,UAAU,KAAK,IAA/E,EAAW,KAAK,QAAQ,SAAS;CACnE,OAAO;EACL,GAAG,EAAQ;EACX,UAAU,EAAoC;GAC5C,GAAG;GACH,WAAW,EAAO,kBAAkB,EAAQ,OAAO;EACrD,CAAC;EACD,UAAU,EAAQ,OAAO,WAAW,OAAS;EAC7C,eAAe,EAAyB,GAAQ,CAAU;CAC5D;AACF"}
@@ -1,5 +1,4 @@
1
1
  export * from '../../../shared/resolvers/index.js';
2
- export * from './resolve-fee-rates.js';
3
2
  export * from './resolve-locked-params.js';
4
3
  export * from './types.js';
5
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/solvers/instant-open/prepare-instant-open-params/resolvers/index.ts"],"names":[],"mappings":"AAGA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/solvers/instant-open/prepare-instant-open-params/resolvers/index.ts"],"names":[],"mappings":"AAGA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,SAAS,CAAC"}
@@ -0,0 +1,164 @@
1
+ import { InstantOpenConstraintFields } from './quote-constraints.js';
2
+ import { CalculateTradeParamsParameters, CalculateTradeParamsReturnType, ComputePlatformFeeRates } from './trade-math.js';
3
+ /**
4
+ * Safety headroom shaved off a full-balance position after it is sized to fit
5
+ * the balance — `0.1%`. The sizing budgets settlement at the *expected* fill;
6
+ * this epsilon (plus the maintenance-margin buffer already in `partyAmm`)
7
+ * absorbs the gap when the actual fill lands a hair worse than the estimate,
8
+ * so the funded VA never opens under-margined by a rounding hair.
9
+ */
10
+ export declare const FULL_BALANCE_SAFETY_EPSILON_PERCENT = 0.1;
11
+ /**
12
+ * Every **open-side** cost leg an instant open charges, plus the `addMargin`
13
+ * amount that funds them. Close fees are not priced here — they are charged at
14
+ * close from the position; preview them with `getInstantCloseFees`. All values
15
+ * are decimal strings.
16
+ */
17
+ export interface InstantOpenCostLegs {
18
+ /** Platform open fee: `getFeeForUser.openFee × notional / 1e18`. */
19
+ platformOpenFee: string;
20
+ /** Solver open fee (`hedgerFeeOpen × notional`). `"0"` on non-lowcap solvers. */
21
+ openSolverFee: string;
22
+ /** Static solver fee charged per instant open — flat USD (solver `/info`). `"0"` on non-lowcap solvers or when unpublished. */
23
+ staticSolverFeeOpen: string;
24
+ /** Side-aware `max(0, adverse fill deviation × quantity)`. `"0"` without a usable fill price. */
25
+ expectedSettlementLoss: string;
26
+ /**
27
+ * The `addMargin` amount the sized trade needs: locked margin (SHORT: at the
28
+ * buffered mark basis) plus every open-side fee leg above.
29
+ */
30
+ marginAmount: string;
31
+ }
32
+ /**
33
+ * Parameters for {@link computeInstantOpenCosts}.
34
+ */
35
+ export interface ComputeInstantOpenCostsParameters {
36
+ /** The sized trade the costs are computed for. */
37
+ trade: CalculateTradeParamsReturnType;
38
+ /** Position side. */
39
+ positionType: CalculateTradeParamsParameters["positionType"];
40
+ /** Mark price the order was sized at (decimal string). */
41
+ markPrice: string;
42
+ /** Expected fill price for the settlement provision; `undefined` provisions `"0"`. */
43
+ expectedFillPrice: string | undefined;
44
+ /** On-chain platform fee rates (`getFeeForUser`). */
45
+ feeRates: ComputePlatformFeeRates;
46
+ /** Lowcap adds the solver fee legs and the SHORT funding buffer; majors carry the platform leg only. */
47
+ isLowcap: boolean;
48
+ /** Solver open-fee rate (decimal fraction string). Lowcap only. */
49
+ hedgerFeeOpen?: string;
50
+ /** Static solver fee per instant open — flat USD, size-independent (solver `/info`). Lowcap only. */
51
+ staticSolverFeeOpen?: string;
52
+ /** Solver locked-param percents — needed for the SHORT buffered-basis recompute. */
53
+ cvaPercent?: string;
54
+ /** Solver locked-param percents. */
55
+ lfPercent?: string;
56
+ /** Solver locked-param percents. */
57
+ partyAmmPercent?: string;
58
+ }
59
+ /**
60
+ * Price every **open-side** cost leg of a sized instant open and the
61
+ * `addMargin` amount that funds them — the one shared cost model behind
62
+ * `prepareInstantOpenParams` and `getInstantOpenFees`, so the preview equals
63
+ * what the open charges by construction. Close fees are charged at close from
64
+ * the position and are priced by `getInstantCloseFees` in the close flow, not
65
+ * here.
66
+ *
67
+ * Pure in `trade`: at a fixed fill price every size-dependent leg scales
68
+ * linearly with the sizing input (rates × notional, price delta × quantity,
69
+ * percents × notionalBasic), which is what lets
70
+ * {@link sizeFullBalanceInstantOpen} solve the full-balance factor in one pass.
71
+ * The static open fee is the exception — a flat USD constant — so the sizing
72
+ * carves it off the balance up front instead of scaling it.
73
+ */
74
+ export declare function computeInstantOpenCosts(parameters: ComputeInstantOpenCostsParameters): InstantOpenCostLegs;
75
+ /**
76
+ * Parameters for {@link sizeFullBalanceInstantOpen}.
77
+ */
78
+ export interface SizeFullBalanceInstantOpenParameters {
79
+ /** The entire collateral to deploy into the VA, as a USD decimal string. */
80
+ balance: string;
81
+ /**
82
+ * Trade-calc input with the final `slippage` resolved. `userInput` /
83
+ * `inputField` are overridden internally (the balance is the sizing probe).
84
+ * The position side, leverage, precisions, and locked-param percents are
85
+ * read from here.
86
+ */
87
+ calculationInput: CalculateTradeParamsParameters;
88
+ /**
89
+ * Solver estimated fill price, when available. When `undefined` the
90
+ * settlement leg is provisioned at the **slippage bound**
91
+ * (`requestedOpenPrice` vs mark) instead of `"0"` — a full-balance open
92
+ * deploys everything, so an unavailable estimate must fail safe, not
93
+ * optimistic.
94
+ */
95
+ expectedFillPrice: string | undefined;
96
+ /** On-chain platform fee rates (`getFeeForUser`). */
97
+ feeRates: ComputePlatformFeeRates;
98
+ /** Solver open-fee rate (decimal fraction string). */
99
+ hedgerFeeOpen?: string;
100
+ /**
101
+ * Static solver fee per instant open — flat USD, size-independent (solver
102
+ * `/info`). Carved off the balance before the linear solve.
103
+ */
104
+ staticSolverFeeOpen?: string;
105
+ /**
106
+ * Market quote constraints. The sized quantity is snapped down to the lot
107
+ * grid and validated against every published constraint; unpublished
108
+ * (`"0"` / `0`) fields skip their check.
109
+ */
110
+ constraints: InstantOpenConstraintFields;
111
+ }
112
+ /**
113
+ * Return type of {@link sizeFullBalanceInstantOpen}.
114
+ */
115
+ export interface SizeFullBalanceInstantOpenReturnType {
116
+ /** The final sized trade — lot-snapped, invariant-checked. */
117
+ trade: CalculateTradeParamsReturnType;
118
+ /** Open-side cost legs of the final trade. `costs.marginAmount ≤ balance` is guaranteed. */
119
+ costs: InstantOpenCostLegs;
120
+ }
121
+ /**
122
+ * Size a full-balance instant open: the largest quantity whose locked margin +
123
+ * open fees + settlement provision fit inside `balance`, on the market's
124
+ * quantity grid. Close fees are charged at close from the position, so they do
125
+ * not join the budget.
126
+ *
127
+ * Steps:
128
+ * 1. **Probe** — run {@link calculateTradeParams} with the whole balance as
129
+ * margin input and price its costs. Every leg is linear in the sizing input
130
+ * at a fixed fill, so `balance / probeMargin` is the exact factor that makes
131
+ * the costs equal the balance.
132
+ * 2. **Rescale** by that factor less {@link FULL_BALANCE_SAFETY_EPSILON_PERCENT}.
133
+ * 3. **Snap** the rescaled quantity **down** to the market's lot grid (when
134
+ * published), rebuilding the locked values from the exact snapped quantity.
135
+ * 4. **Invariant** — recompute the costs and, while `marginAmount > balance`,
136
+ * step the quantity down one grid step. The linear model only mispredicts
137
+ * through precision rounding (worth at most a few quanta), so this loop is
138
+ * short and guarantees the funded VA is never smaller than what the signed
139
+ * quote locks.
140
+ * 5. **Validate** the final quantity against the market's published quote
141
+ * constraints.
142
+ *
143
+ * The settlement leg is provisioned at the expected fill when one exists, and
144
+ * at the slippage bound otherwise — never at zero, because a full-balance open
145
+ * leaves nothing behind to absorb an optimistic estimate. The estimate is
146
+ * trusted only at or below the probe size it was quoted for: when the factor
147
+ * would upsize past the probe (locks percents summing under 100), the sizing
148
+ * re-solves with settlement at the slippage bound, or clamps to the probe
149
+ * size when the bound model no longer upsizes.
150
+ *
151
+ * The static open fee (flat USD, size-independent) would break the linear
152
+ * factor solve, so it is carved off the balance first: the position is sized
153
+ * against `balance − staticSolverFeeOpen`, which keeps the solve exact, and the
154
+ * reported costs then re-add it — `marginAmount ≤ balance` still holds by
155
+ * construction.
156
+ *
157
+ * @throws {SymmError} `INVALID_TRADE_PARAMETERS` when the inputs cannot size a
158
+ * positive quantity whose costs fit the balance (including a balance that
159
+ * cannot even cover the static open fee);
160
+ * `QUOTE_CONSTRAINT_VIOLATED` when the sized quantity violates a published
161
+ * market constraint.
162
+ */
163
+ export declare function sizeFullBalanceInstantOpen(parameters: SizeFullBalanceInstantOpenParameters): SizeFullBalanceInstantOpenReturnType;
164
+ //# sourceMappingURL=full-balance-sizing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full-balance-sizing.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/shared/full-balance-sizing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EACV,8BAA8B,EAC9B,8BAA8B,EAC9B,uBAAuB,EACxB,MAAM,cAAc,CAAC;AAUtB;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,MAAM,CAAC;AAUvD;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,eAAe,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,aAAa,EAAE,MAAM,CAAC;IACtB,+HAA+H;IAC/H,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iGAAiG;IACjG,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,kDAAkD;IAClD,KAAK,EAAE,8BAA8B,CAAC;IACtC,qBAAqB;IACrB,YAAY,EAAE,8BAA8B,CAAC,cAAc,CAAC,CAAC;IAC7D,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,qDAAqD;IACrD,QAAQ,EAAE,uBAAuB,CAAC;IAClC,wGAAwG;IACxG,QAAQ,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qGAAqG;IACrG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,iCAAiC,GAAG,mBAAmB,CA2C1G;AAED;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,gBAAgB,EAAE,8BAA8B,CAAC;IACjD;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,qDAAqD;IACrD,QAAQ,EAAE,uBAAuB,CAAC;IAClC,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,WAAW,EAAE,2BAA2B,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,8DAA8D;IAC9D,KAAK,EAAE,8BAA8B,CAAC;IACtC,4FAA4F;IAC5F,KAAK,EAAE,mBAAmB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,oCAAoC,GAC/C,oCAAoC,CAoJtC"}
@@ -0,0 +1,138 @@
1
+ import { SymmError as e } from "../../../shared/errors/symm-error.js";
2
+ import { calculateExpectedSettlementLoss as t, calculateMargin as n, calculateSolverFees as r, calculateTradeParams as i, computePlatformFeeLegs as a } from "./trade-math.js";
3
+ import { validateInstantOpenAgainstMarket as o } from "./quote-constraints.js";
4
+ import { toDecimal as s } from "@symmio/utils/decimal";
5
+ //#region src/solvers/instant-open/shared/full-balance-sizing.ts
6
+ var c = .1, l = 25;
7
+ function u(e) {
8
+ let { trade: i, positionType: o, markPrice: s, expectedFillPrice: c, feeRates: l, isLowcap: u } = e, { platformOpenFee: d } = a(l, i.notional, i.notional), { openSolverFee: f, staticSolverFeeOpen: p } = u ? r({
9
+ notional: i.notional,
10
+ hedgerFeeOpen: e.hedgerFeeOpen,
11
+ hedgerFeeClose: void 0,
12
+ staticSolverFeeOpen: e.staticSolverFeeOpen
13
+ }) : {
14
+ openSolverFee: "0",
15
+ staticSolverFeeOpen: "0"
16
+ }, m = t({
17
+ positionType: o,
18
+ markPrice: s,
19
+ expectedFillPrice: c,
20
+ quantity: i.quantity
21
+ });
22
+ return {
23
+ platformOpenFee: d,
24
+ openSolverFee: f,
25
+ staticSolverFeeOpen: p,
26
+ expectedSettlementLoss: m,
27
+ marginAmount: n({
28
+ positionType: o,
29
+ markPrice: s,
30
+ quantityBasic: i.quantityBasic,
31
+ cva: i.cva,
32
+ lf: i.lf,
33
+ partyAmm: i.partyAmm,
34
+ openSolverFee: f,
35
+ staticSolverFeeOpen: p,
36
+ expectedSettlementLoss: m,
37
+ platformFee: d,
38
+ shortFundingBufferPercent: +!!u,
39
+ cvaPercent: e.cvaPercent,
40
+ lfPercent: e.lfPercent,
41
+ partyAmmPercent: e.partyAmmPercent
42
+ })
43
+ };
44
+ }
45
+ function d(t) {
46
+ let { balance: n, calculationInput: r, feeRates: a, constraints: d } = t, p = t.staticSolverFeeOpen ?? "0", m = s(n).minus(p);
47
+ if (m.isNaN() || m.lte(0)) throw new e("validation", "INVALID_TRADE_PARAMETERS", "sizeFullBalanceInstantOpen: the balance cannot cover the solver's static open fee.");
48
+ let h = m.toString(), g = i({
49
+ ...r,
50
+ userInput: h,
51
+ inputField: "PRICE"
52
+ });
53
+ if (!g) throw new e("validation", "INVALID_TRADE_PARAMETERS", "Invalid trade parameters: markPrice or balance is zero/NaN.");
54
+ let _ = {
55
+ positionType: r.positionType,
56
+ markPrice: r.markPrice,
57
+ feeRates: a,
58
+ isLowcap: !0,
59
+ hedgerFeeOpen: t.hedgerFeeOpen,
60
+ cvaPercent: r.cvaPercent,
61
+ lfPercent: r.lfPercent,
62
+ partyAmmPercent: r.partyAmmPercent
63
+ }, v = g.requestedOpenPrice, y = t.expectedFillPrice ?? v, b = s(u({
64
+ ..._,
65
+ expectedFillPrice: y,
66
+ trade: g
67
+ }).marginAmount);
68
+ if (b.isNaN() || b.lte(0)) throw new e("validation", "INVALID_TRADE_PARAMETERS", "sizeFullBalanceInstantOpen: could not size the full-balance open — the probe margin is zero or invalid.");
69
+ let x = s(100 - c).div(100), S = s(h).div(b).times(x);
70
+ if (S.gt(1) && t.expectedFillPrice !== void 0) {
71
+ let e = s(u({
72
+ ..._,
73
+ expectedFillPrice: v,
74
+ trade: g
75
+ }).marginAmount), t = s(h).div(e).times(x);
76
+ t.gt(1) ? (S = t, y = v) : S = x;
77
+ }
78
+ let C = i({
79
+ ...r,
80
+ userInput: s(h).times(S).toString(),
81
+ inputField: "PRICE"
82
+ });
83
+ if (!C) throw new e("validation", "INVALID_TRADE_PARAMETERS", "sizeFullBalanceInstantOpen: the rescaled sizing input is zero/NaN — the balance is too small to open.");
84
+ let w = s(d.lotSize), T = !w.isNaN() && w.gt(0), E = T ? w : s(`1e-${r.quantityPrecision}`), D = s(C.quantity);
85
+ T && (D = D.minus(D.mod(w)));
86
+ let O = f(D.toString(), r, g.requestedOpenPrice), k = u({
87
+ ..._,
88
+ expectedFillPrice: y,
89
+ trade: O
90
+ });
91
+ for (let t = 0; s(k.marginAmount).gt(h); t++) {
92
+ if (D = D.minus(E), D.lte(0) || t >= l) throw new e("validation", "INVALID_TRADE_PARAMETERS", "sizeFullBalanceInstantOpen: the balance cannot fund even the smallest quantity step on this market.");
93
+ O = f(D.toString(), r, g.requestedOpenPrice), k = u({
94
+ ..._,
95
+ expectedFillPrice: y,
96
+ trade: O
97
+ });
98
+ }
99
+ let { ok: A, violations: j } = o({
100
+ market: d,
101
+ quantity: O.quantity,
102
+ markPrice: r.markPrice,
103
+ cva: O.cva,
104
+ lf: O.lf,
105
+ partyAmm: O.partyAmm
106
+ });
107
+ if (!A) {
108
+ let t = j.map((e) => e.kind).join(", ");
109
+ throw new e("validation", "QUOTE_CONSTRAINT_VIOLATED", `sizeFullBalanceInstantOpen: the sized quantity ${O.quantity} violates market constraints: ${t}.`);
110
+ }
111
+ return k = u({
112
+ ..._,
113
+ staticSolverFeeOpen: p,
114
+ expectedFillPrice: y,
115
+ trade: O
116
+ }), {
117
+ trade: O,
118
+ costs: k
119
+ };
120
+ }
121
+ function f(e, t, n) {
122
+ let r = s(e).div(t.leverage).toString(), i = s(r).times(n).toString(), a = (e) => s(i).times(s(e)).div(100).toString();
123
+ return {
124
+ requestedOpenPrice: n,
125
+ quantityBasic: r,
126
+ quantity: e,
127
+ notionalBasic: i,
128
+ notional: s(i).times(t.leverage).toString(),
129
+ cva: a(t.cvaPercent),
130
+ lf: a(t.lfPercent),
131
+ partyAmm: a(t.partyAmmPercent),
132
+ partyBmm: a(t.partyBmmPercent)
133
+ };
134
+ }
135
+ //#endregion
136
+ export { u as computeInstantOpenCosts, d as sizeFullBalanceInstantOpen };
137
+
138
+ //# sourceMappingURL=full-balance-sizing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full-balance-sizing.js","names":[],"sources":["../../../../src/solvers/instant-open/shared/full-balance-sizing.ts"],"sourcesContent":["import { toDecimal } from \"@symmio/utils/decimal\";\nimport { SymmError } from \"../../../shared/errors/symm-error\";\nimport type { InstantOpenConstraintFields } from \"./quote-constraints\";\nimport { validateInstantOpenAgainstMarket } from \"./quote-constraints\";\nimport type {\n CalculateTradeParamsParameters,\n CalculateTradeParamsReturnType,\n ComputePlatformFeeRates,\n} from \"./trade-math\";\nimport {\n calculateExpectedSettlementLoss,\n calculateMargin,\n calculateSolverFees,\n calculateTradeParams,\n computePlatformFeeLegs,\n SHORT_FUNDING_BUFFER_PERCENT,\n} from \"./trade-math\";\n\n/**\n * Safety headroom shaved off a full-balance position after it is sized to fit\n * the balance — `0.1%`. The sizing budgets settlement at the *expected* fill;\n * this epsilon (plus the maintenance-margin buffer already in `partyAmm`)\n * absorbs the gap when the actual fill lands a hair worse than the estimate,\n * so the funded VA never opens under-margined by a rounding hair.\n */\nexport const FULL_BALANCE_SAFETY_EPSILON_PERCENT = 0.1;\n\n/**\n * Hard cap on the invariant step-down loop in\n * {@link sizeFullBalanceInstantOpen}. The linear rescale can overshoot by at\n * most a few quantity quanta (probe-side rounding), so hitting this cap means\n * the inputs are degenerate, not that more iterations would help.\n */\nconst MAX_STEP_DOWN_ITERATIONS = 25;\n\n/**\n * Every **open-side** cost leg an instant open charges, plus the `addMargin`\n * amount that funds them. Close fees are not priced here — they are charged at\n * close from the position; preview them with `getInstantCloseFees`. All values\n * are decimal strings.\n */\nexport interface InstantOpenCostLegs {\n /** Platform open fee: `getFeeForUser.openFee × notional / 1e18`. */\n platformOpenFee: string;\n /** Solver open fee (`hedgerFeeOpen × notional`). `\"0\"` on non-lowcap solvers. */\n openSolverFee: string;\n /** Static solver fee charged per instant open — flat USD (solver `/info`). `\"0\"` on non-lowcap solvers or when unpublished. */\n staticSolverFeeOpen: string;\n /** Side-aware `max(0, adverse fill deviation × quantity)`. `\"0\"` without a usable fill price. */\n expectedSettlementLoss: string;\n /**\n * The `addMargin` amount the sized trade needs: locked margin (SHORT: at the\n * buffered mark basis) plus every open-side fee leg above.\n */\n marginAmount: string;\n}\n\n/**\n * Parameters for {@link computeInstantOpenCosts}.\n */\nexport interface ComputeInstantOpenCostsParameters {\n /** The sized trade the costs are computed for. */\n trade: CalculateTradeParamsReturnType;\n /** Position side. */\n positionType: CalculateTradeParamsParameters[\"positionType\"];\n /** Mark price the order was sized at (decimal string). */\n markPrice: string;\n /** Expected fill price for the settlement provision; `undefined` provisions `\"0\"`. */\n expectedFillPrice: string | undefined;\n /** On-chain platform fee rates (`getFeeForUser`). */\n feeRates: ComputePlatformFeeRates;\n /** Lowcap adds the solver fee legs and the SHORT funding buffer; majors carry the platform leg only. */\n isLowcap: boolean;\n /** Solver open-fee rate (decimal fraction string). Lowcap only. */\n hedgerFeeOpen?: string;\n /** Static solver fee per instant open — flat USD, size-independent (solver `/info`). Lowcap only. */\n staticSolverFeeOpen?: string;\n /** Solver locked-param percents — needed for the SHORT buffered-basis recompute. */\n cvaPercent?: string;\n /** Solver locked-param percents. */\n lfPercent?: string;\n /** Solver locked-param percents. */\n partyAmmPercent?: string;\n}\n\n/**\n * Price every **open-side** cost leg of a sized instant open and the\n * `addMargin` amount that funds them — the one shared cost model behind\n * `prepareInstantOpenParams` and `getInstantOpenFees`, so the preview equals\n * what the open charges by construction. Close fees are charged at close from\n * the position and are priced by `getInstantCloseFees` in the close flow, not\n * here.\n *\n * Pure in `trade`: at a fixed fill price every size-dependent leg scales\n * linearly with the sizing input (rates × notional, price delta × quantity,\n * percents × notionalBasic), which is what lets\n * {@link sizeFullBalanceInstantOpen} solve the full-balance factor in one pass.\n * The static open fee is the exception — a flat USD constant — so the sizing\n * carves it off the balance up front instead of scaling it.\n */\nexport function computeInstantOpenCosts(parameters: ComputeInstantOpenCostsParameters): InstantOpenCostLegs {\n const { trade, positionType, markPrice, expectedFillPrice, feeRates, isLowcap } = parameters;\n\n const { platformOpenFee } = computePlatformFeeLegs(feeRates, trade.notional, trade.notional);\n const { openSolverFee, staticSolverFeeOpen } = isLowcap\n ? calculateSolverFees({\n notional: trade.notional,\n hedgerFeeOpen: parameters.hedgerFeeOpen,\n hedgerFeeClose: undefined,\n staticSolverFeeOpen: parameters.staticSolverFeeOpen,\n })\n : { openSolverFee: \"0\", staticSolverFeeOpen: \"0\" };\n const expectedSettlementLoss = calculateExpectedSettlementLoss({\n positionType,\n markPrice,\n expectedFillPrice,\n quantity: trade.quantity,\n });\n const marginAmount = calculateMargin({\n positionType,\n markPrice,\n quantityBasic: trade.quantityBasic,\n cva: trade.cva,\n lf: trade.lf,\n partyAmm: trade.partyAmm,\n openSolverFee,\n staticSolverFeeOpen,\n expectedSettlementLoss,\n platformFee: platformOpenFee,\n /** Lowcap SHORT: fund lock growth above the floor. Majors keep the classic basis. */\n shortFundingBufferPercent: isLowcap ? SHORT_FUNDING_BUFFER_PERCENT : 0,\n cvaPercent: parameters.cvaPercent,\n lfPercent: parameters.lfPercent,\n partyAmmPercent: parameters.partyAmmPercent,\n });\n\n return {\n platformOpenFee,\n openSolverFee,\n staticSolverFeeOpen,\n expectedSettlementLoss,\n marginAmount,\n };\n}\n\n/**\n * Parameters for {@link sizeFullBalanceInstantOpen}.\n */\nexport interface SizeFullBalanceInstantOpenParameters {\n /** The entire collateral to deploy into the VA, as a USD decimal string. */\n balance: string;\n /**\n * Trade-calc input with the final `slippage` resolved. `userInput` /\n * `inputField` are overridden internally (the balance is the sizing probe).\n * The position side, leverage, precisions, and locked-param percents are\n * read from here.\n */\n calculationInput: CalculateTradeParamsParameters;\n /**\n * Solver estimated fill price, when available. When `undefined` the\n * settlement leg is provisioned at the **slippage bound**\n * (`requestedOpenPrice` vs mark) instead of `\"0\"` — a full-balance open\n * deploys everything, so an unavailable estimate must fail safe, not\n * optimistic.\n */\n expectedFillPrice: string | undefined;\n /** On-chain platform fee rates (`getFeeForUser`). */\n feeRates: ComputePlatformFeeRates;\n /** Solver open-fee rate (decimal fraction string). */\n hedgerFeeOpen?: string;\n /**\n * Static solver fee per instant open — flat USD, size-independent (solver\n * `/info`). Carved off the balance before the linear solve.\n */\n staticSolverFeeOpen?: string;\n /**\n * Market quote constraints. The sized quantity is snapped down to the lot\n * grid and validated against every published constraint; unpublished\n * (`\"0\"` / `0`) fields skip their check.\n */\n constraints: InstantOpenConstraintFields;\n}\n\n/**\n * Return type of {@link sizeFullBalanceInstantOpen}.\n */\nexport interface SizeFullBalanceInstantOpenReturnType {\n /** The final sized trade — lot-snapped, invariant-checked. */\n trade: CalculateTradeParamsReturnType;\n /** Open-side cost legs of the final trade. `costs.marginAmount ≤ balance` is guaranteed. */\n costs: InstantOpenCostLegs;\n}\n\n/**\n * Size a full-balance instant open: the largest quantity whose locked margin +\n * open fees + settlement provision fit inside `balance`, on the market's\n * quantity grid. Close fees are charged at close from the position, so they do\n * not join the budget.\n *\n * Steps:\n * 1. **Probe** — run {@link calculateTradeParams} with the whole balance as\n * margin input and price its costs. Every leg is linear in the sizing input\n * at a fixed fill, so `balance / probeMargin` is the exact factor that makes\n * the costs equal the balance.\n * 2. **Rescale** by that factor less {@link FULL_BALANCE_SAFETY_EPSILON_PERCENT}.\n * 3. **Snap** the rescaled quantity **down** to the market's lot grid (when\n * published), rebuilding the locked values from the exact snapped quantity.\n * 4. **Invariant** — recompute the costs and, while `marginAmount > balance`,\n * step the quantity down one grid step. The linear model only mispredicts\n * through precision rounding (worth at most a few quanta), so this loop is\n * short and guarantees the funded VA is never smaller than what the signed\n * quote locks.\n * 5. **Validate** the final quantity against the market's published quote\n * constraints.\n *\n * The settlement leg is provisioned at the expected fill when one exists, and\n * at the slippage bound otherwise — never at zero, because a full-balance open\n * leaves nothing behind to absorb an optimistic estimate. The estimate is\n * trusted only at or below the probe size it was quoted for: when the factor\n * would upsize past the probe (locks percents summing under 100), the sizing\n * re-solves with settlement at the slippage bound, or clamps to the probe\n * size when the bound model no longer upsizes.\n *\n * The static open fee (flat USD, size-independent) would break the linear\n * factor solve, so it is carved off the balance first: the position is sized\n * against `balance − staticSolverFeeOpen`, which keeps the solve exact, and the\n * reported costs then re-add it — `marginAmount ≤ balance` still holds by\n * construction.\n *\n * @throws {SymmError} `INVALID_TRADE_PARAMETERS` when the inputs cannot size a\n * positive quantity whose costs fit the balance (including a balance that\n * cannot even cover the static open fee);\n * `QUOTE_CONSTRAINT_VIOLATED` when the sized quantity violates a published\n * market constraint.\n */\nexport function sizeFullBalanceInstantOpen(\n parameters: SizeFullBalanceInstantOpenParameters,\n): SizeFullBalanceInstantOpenReturnType {\n const { balance, calculationInput, feeRates, constraints } = parameters;\n\n // Flat leg off the top: the linear solve below only holds for costs that\n // scale with the sizing input, so the size-independent static open fee\n // shrinks the budget instead of joining the solve.\n const staticSolverFeeOpen = parameters.staticSolverFeeOpen ?? \"0\";\n const effectiveBalanceDec = toDecimal(balance).minus(staticSolverFeeOpen);\n if (effectiveBalanceDec.isNaN() || effectiveBalanceDec.lte(0)) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"sizeFullBalanceInstantOpen: the balance cannot cover the solver's static open fee.\",\n );\n }\n const effectiveBalance = effectiveBalanceDec.toString();\n\n const probe = calculateTradeParams({ ...calculationInput, userInput: effectiveBalance, inputField: \"PRICE\" });\n if (!probe) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"Invalid trade parameters: markPrice or balance is zero/NaN.\",\n );\n }\n\n // Deliberately WITHOUT the static open leg: every cost this context prices is\n // linear in the sizing input, and the solve runs against `effectiveBalance`.\n const costsContext = {\n positionType: calculationInput.positionType,\n markPrice: calculationInput.markPrice,\n feeRates,\n isLowcap: true,\n hedgerFeeOpen: parameters.hedgerFeeOpen,\n cvaPercent: calculationInput.cvaPercent,\n lfPercent: calculationInput.lfPercent,\n partyAmmPercent: calculationInput.partyAmmPercent,\n } as const;\n\n // Fail safe, not optimistic: without an estimate the settlement leg is\n // provisioned at the worst fill the signed price bound admits.\n const boundFillPrice = probe.requestedOpenPrice;\n let settlementFillPrice = parameters.expectedFillPrice ?? boundFillPrice;\n\n const probeMargin = toDecimal(\n computeInstantOpenCosts({ ...costsContext, expectedFillPrice: settlementFillPrice, trade: probe }).marginAmount,\n );\n // `Decimal(0).isPositive()` is true (zero carries a positive sign), so an\n // explicit lte(0) is required to keep a cost-free market from dividing to\n // Infinity below.\n if (probeMargin.isNaN() || probeMargin.lte(0)) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"sizeFullBalanceInstantOpen: could not size the full-balance open — the probe margin is zero or invalid.\",\n );\n }\n\n const epsilonFactor = toDecimal(100 - FULL_BALANCE_SAFETY_EPSILON_PERCENT).div(100);\n let sizingFactor = toDecimal(effectiveBalance).div(probeMargin).times(epsilonFactor);\n // The estimate was quoted at the probe size, so it only bounds fills at or\n // below it. A factor above 1 upsizes PAST the probe; there the estimate is\n // no longer conservative, so re-solve with settlement at the slippage bound\n // — and when even that stays above 1, upsize under the bound model. When\n // the bound model lands at or below the probe size, clamp to the probe size\n // instead, where the estimate is still valid.\n if (sizingFactor.gt(1) && parameters.expectedFillPrice !== undefined) {\n const probeMarginBound = toDecimal(\n computeInstantOpenCosts({ ...costsContext, expectedFillPrice: boundFillPrice, trade: probe }).marginAmount,\n );\n const boundFactor = toDecimal(effectiveBalance).div(probeMarginBound).times(epsilonFactor);\n if (boundFactor.gt(1)) {\n sizingFactor = boundFactor;\n settlementFillPrice = boundFillPrice;\n } else {\n sizingFactor = epsilonFactor;\n }\n }\n const rescaled = calculateTradeParams({\n ...calculationInput,\n userInput: toDecimal(effectiveBalance).times(sizingFactor).toString(),\n inputField: \"PRICE\",\n });\n if (!rescaled) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"sizeFullBalanceInstantOpen: the rescaled sizing input is zero/NaN — the balance is too small to open.\",\n );\n }\n\n // Quantity grid: the lot size when the market publishes one, else the\n // quantity-precision quantum. Snap down — less quantity always needs less\n // margin, so down is the safe direction.\n const lotSize = toDecimal(constraints.lotSize);\n const hasLotGrid = !lotSize.isNaN() && lotSize.gt(0);\n const step = hasLotGrid ? lotSize : toDecimal(`1e-${calculationInput.quantityPrecision}`);\n\n let quantity = toDecimal(rescaled.quantity);\n if (hasLotGrid) quantity = quantity.minus(quantity.mod(lotSize));\n\n let trade = buildTradeFromQuantity(quantity.toString(), calculationInput, probe.requestedOpenPrice);\n let costs = computeInstantOpenCosts({ ...costsContext, expectedFillPrice: settlementFillPrice, trade });\n\n // Invariant: the funded VA must cover everything the signed quote locks. The\n // linear factor is exact up to precision rounding, so at most a few steps.\n // Compared against the static-open-fee-reduced budget — the static open fee\n // was carved off up front and rejoins the reported costs below.\n for (let iteration = 0; toDecimal(costs.marginAmount).gt(effectiveBalance); iteration++) {\n quantity = quantity.minus(step);\n if (quantity.lte(0) || iteration >= MAX_STEP_DOWN_ITERATIONS) {\n throw new SymmError(\n \"validation\",\n \"INVALID_TRADE_PARAMETERS\",\n \"sizeFullBalanceInstantOpen: the balance cannot fund even the smallest quantity step on this market.\",\n );\n }\n trade = buildTradeFromQuantity(quantity.toString(), calculationInput, probe.requestedOpenPrice);\n costs = computeInstantOpenCosts({ ...costsContext, expectedFillPrice: settlementFillPrice, trade });\n }\n\n const { ok, violations } = validateInstantOpenAgainstMarket({\n market: constraints,\n quantity: trade.quantity,\n markPrice: calculationInput.markPrice,\n cva: trade.cva,\n lf: trade.lf,\n partyAmm: trade.partyAmm,\n });\n if (!ok) {\n const summary = violations.map((violation) => violation.kind).join(\", \");\n throw new SymmError(\n \"validation\",\n \"QUOTE_CONSTRAINT_VIOLATED\",\n `sizeFullBalanceInstantOpen: the sized quantity ${trade.quantity} violates market constraints: ${summary}.`,\n );\n }\n\n // Reported costs carry the static open leg the solve carved off the budget:\n // marginAmount = linear open costs (≤ effectiveBalance) + static open fee ≤ balance.\n costs = computeInstantOpenCosts({\n ...costsContext,\n staticSolverFeeOpen,\n expectedFillPrice: settlementFillPrice,\n trade,\n });\n\n return { trade, costs };\n}\n\n/**\n * Rebuild a full trade-params shape from an exact leveraged quantity.\n *\n * Unlike {@link calculateTradeParams} (which floors `quantityBasic` first and\n * multiplies up), this derives `quantityBasic = quantity / leverage` at full\n * precision so the locked values stay exactly proportional to the wire\n * quantity — the solver re-derives its locks from the quantity it receives, so\n * a floored intermediate would disagree with it.\n */\nfunction buildTradeFromQuantity(\n quantity: string,\n calculationInput: CalculateTradeParamsParameters,\n requestedOpenPrice: string,\n): CalculateTradeParamsReturnType {\n const quantityBasic = toDecimal(quantity).div(calculationInput.leverage).toString();\n const notionalBasic = toDecimal(quantityBasic).times(requestedOpenPrice).toString();\n const percent = (value: string | undefined) => toDecimal(notionalBasic).times(toDecimal(value)).div(100).toString();\n return {\n requestedOpenPrice,\n quantityBasic,\n quantity,\n notionalBasic,\n notional: toDecimal(notionalBasic).times(calculationInput.leverage).toString(),\n cva: percent(calculationInput.cvaPercent),\n lf: percent(calculationInput.lfPercent),\n partyAmm: percent(calculationInput.partyAmmPercent),\n partyBmm: percent(calculationInput.partyBmmPercent),\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export * from './calldata.js';
2
2
  export * from './eip712.js';
3
+ export * from './full-balance-sizing.js';
3
4
  export * from './hedger-api.js';
4
5
  export * from './open-estimate-guard.js';
5
6
  export * from './operations.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}