@symmio/trading-core 3.3.0 → 3.4.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.
@@ -25,7 +25,7 @@ async function u(u, d) {
25
25
  deadline: _,
26
26
  affiliate: S,
27
27
  data: y,
28
- upnlSig: o(d.order.price)
28
+ upnlSig: o(d.markPrice ?? d.order.price)
29
29
  }, T = m.contractsVersion === "0.8.5" ? a(w) : i({
30
30
  ...w,
31
31
  solverFeeCaps: d.solverFeeCaps
@@ -34,14 +34,14 @@ async function u(u, d) {
34
34
  target: b,
35
35
  callData: C,
36
36
  signerAccount: d.subAccountAddress,
37
- deadline: _,
37
+ deadline: d.operationDeadline ?? _,
38
38
  salt: d.addMarginSalt
39
39
  }), D = t({
40
40
  signer: g,
41
41
  target: x,
42
42
  callData: T,
43
43
  signerAccount: d.subAccountAddress,
44
- deadline: _,
44
+ deadline: d.operationDeadline ?? _,
45
45
  salt: d.sendQuoteSalt,
46
46
  flexFields: [{
47
47
  ...s(T),
@@ -1 +1 @@
1
- {"version":3,"file":"enigma-instant-open.js","names":[],"sources":["../../../../../src/solvers/instant-open/instant-open/adapters/enigma-instant-open.ts"],"sourcesContent":["import { SymmError } from \"../../../../shared/errors/symm-error\";\nimport {\n encodeAddMarginToNextVA,\n encodeSendQuote,\n encodeSendQuoteWithAffiliateAndData,\n getFakeSendQuoteMuonSignature,\n sendQuoteUpnlSigFlexRange,\n} from \"../../shared/calldata\";\nimport { sendInstantOpen } from \"../../shared/hedger-api\";\nimport { buildSignedOperation, signAndFormatInstantOperation } from \"../../shared/operations\";\nimport { ORDER_TYPE_MARKET, isolationTypeForSide } from \"../../shared/types\";\nimport type { EnigmaInstantOpenResult, InstantOpenParameters } from \"../types\";\nimport type { InstantOpenAdapterContext } from \"./context\";\n\n/**\n * Submit an instant open to an **Enigma** (lowcap) hedger.\n *\n * Signs two operations — `addMarginToNextVA` on the AccountLayer and\n * `sendQuote` on the diamond — and posts both to `/instant_trade/instant_open`.\n *\n * The quote carries a **placeholder** Muon signature: lowcap bypasses Muon\n * verification, but the contract still reads `upnlSig.price`, and the encoded\n * signature region is delegated to the solver via a `FlexField` so it can write a\n * live attestation at execution time. Only the `sendQuote` operation carries the\n * delegation; `addMargin` stays fully fixed.\n *\n * @throws {SymmError} `INSTANT_OPEN_MARGIN_REQUIRED` when `margin` is absent —\n * reachable when the caller omitted `solverId` and the chain's default solver\n * turned out to be Enigma.\n * @throws {SymmApiError} when the hedger request fails.\n * @internal\n */\nexport async function submitEnigmaInstantOpen(\n context: InstantOpenAdapterContext,\n parameters: InstantOpenParameters,\n): Promise<EnigmaInstantOpenResult> {\n if (!parameters.margin) {\n throw new SymmError(\n \"validation\",\n \"INSTANT_OPEN_MARGIN_REQUIRED\",\n \"instantOpen: the Enigma (lowcap) flow funds a new virtual account, so `margin.amount` is required.\",\n );\n }\n\n const { config, solver, chainConfig, walletClient, signerAddress, deadline, symbolId, metadata } = context;\n const { accountLayerAddress, symmioAddress, affiliatesAddress } = chainConfig.addresses;\n\n const addMarginCallData = encodeAddMarginToNextVA({\n subAccount: parameters.subAccountAddress,\n isolationType: isolationTypeForSide(parameters.positionType),\n symbolId,\n amount: parameters.margin.amount,\n });\n\n const quoteArgs = {\n partyBsWhiteList: [solver.address],\n symbolId,\n positionType: parameters.positionType,\n orderType: ORDER_TYPE_MARKET,\n price: parameters.order.price,\n quantity: parameters.order.quantity,\n cva: parameters.lockedParam.cva,\n lf: parameters.lockedParam.lf,\n partyAmm: parameters.lockedParam.partyAmm,\n partyBmm: parameters.lockedParam.partyBmm,\n deadline,\n affiliate: affiliatesAddress,\n data: metadata,\n upnlSig: getFakeSendQuoteMuonSignature(parameters.order.price),\n };\n\n /**\n * Which quote-send call to sign is a chain-generation fact: a v0.8.5 diamond\n * has no capped `sendQuote` selector (the calldata would revert), and a\n * v0.8.6 solver rejects the legacy call's zero fee caps.\n */\n const sendQuoteCallData =\n chainConfig.contractsVersion === \"0.8.5\"\n ? encodeSendQuoteWithAffiliateAndData(quoteArgs)\n : encodeSendQuote({ ...quoteArgs, solverFeeCaps: parameters.solverFeeCaps });\n\n const addMarginOp = buildSignedOperation({\n signer: signerAddress,\n target: accountLayerAddress,\n callData: addMarginCallData,\n signerAccount: parameters.subAccountAddress,\n deadline,\n salt: parameters.addMarginSalt,\n });\n\n const sendQuoteOp = buildSignedOperation({\n signer: signerAddress,\n target: symmioAddress,\n callData: sendQuoteCallData,\n signerAccount: parameters.subAccountAddress,\n deadline,\n salt: parameters.sendQuoteSalt,\n flexFields: [{ ...sendQuoteUpnlSigFlexRange(sendQuoteCallData), authorizedFlexFiller: solver.address }],\n });\n\n const [addMargin, sendQuote] = await Promise.all([\n signAndFormatInstantOperation(config, { operation: addMarginOp, chainId: context.chainId, walletClient }),\n signAndFormatInstantOperation(config, { operation: sendQuoteOp, chainId: context.chainId, walletClient }),\n ]);\n\n const response = await sendInstantOpen(config, {\n chainId: context.chainId,\n // The resolved solver's own id — never a hardcoded kind, so a differently-id'd\n // solver of the same kind can never be re-resolved onto the wrong endpoint.\n solverId: solver.id,\n request: { addMargin, sendQuote },\n });\n\n return {\n kind: \"enigma\",\n success: true,\n tempQuoteId:\n response.temp_quote_id !== undefined && response.temp_quote_id !== null\n ? String(response.temp_quote_id)\n : undefined,\n partyBmm: response.partyBmm,\n };\n}\n"],"mappings":";;;;;;AAgCA,eAAsB,EACpB,GACA,GACkC;CAClC,IAAI,CAAC,EAAW,QACd,MAAM,IAAI,EACR,cACA,gCACA,oGACF;CAGF,IAAM,EAAE,WAAQ,WAAQ,gBAAa,iBAAc,kBAAe,aAAU,aAAU,gBAAa,GAC7F,EAAE,wBAAqB,kBAAe,yBAAsB,EAAY,WAExE,IAAoB,EAAwB;EAChD,YAAY,EAAW;EACvB,eAAe,EAAqB,EAAW,YAAY;EAC3D;EACA,QAAQ,EAAW,OAAO;CAC5B,CAAC,GAEK,IAAY;EAChB,kBAAkB,CAAC,EAAO,OAAO;EACjC;EACA,cAAc,EAAW;EACzB,WAAA;EACA,OAAO,EAAW,MAAM;EACxB,UAAU,EAAW,MAAM;EAC3B,KAAK,EAAW,YAAY;EAC5B,IAAI,EAAW,YAAY;EAC3B,UAAU,EAAW,YAAY;EACjC,UAAU,EAAW,YAAY;EACjC;EACA,WAAW;EACX,MAAM;EACN,SAAS,EAA8B,EAAW,MAAM,KAAK;CAC/D,GAOM,IACJ,EAAY,qBAAqB,UAC7B,EAAoC,CAAS,IAC7C,EAAgB;EAAE,GAAG;EAAW,eAAe,EAAW;CAAc,CAAC,GAEzE,IAAc,EAAqB;EACvC,QAAQ;EACR,QAAQ;EACR,UAAU;EACV,eAAe,EAAW;EAC1B;EACA,MAAM,EAAW;CACnB,CAAC,GAEK,IAAc,EAAqB;EACvC,QAAQ;EACR,QAAQ;EACR,UAAU;EACV,eAAe,EAAW;EAC1B;EACA,MAAM,EAAW;EACjB,YAAY,CAAC;GAAE,GAAG,EAA0B,CAAiB;GAAG,sBAAsB,EAAO;EAAQ,CAAC;CACxG,CAAC,GAEK,CAAC,GAAW,KAAa,MAAM,QAAQ,IAAI,CAC/C,EAA8B,GAAQ;EAAE,WAAW;EAAa,SAAS,EAAQ;EAAS;CAAa,CAAC,GACxG,EAA8B,GAAQ;EAAE,WAAW;EAAa,SAAS,EAAQ;EAAS;CAAa,CAAC,CAC1G,CAAC,GAEK,IAAW,MAAM,EAAgB,GAAQ;EAC7C,SAAS,EAAQ;EAGjB,UAAU,EAAO;EACjB,SAAS;GAAE;GAAW;EAAU;CAClC,CAAC;CAED,OAAO;EACL,MAAM;EACN,SAAS;EACT,aACE,EAAS,kBAAkB,KAAA,KAAa,EAAS,kBAAkB,OAC/D,OAAO,EAAS,aAAa,IAC7B,KAAA;EACN,UAAU,EAAS;CACrB;AACF"}
1
+ {"version":3,"file":"enigma-instant-open.js","names":[],"sources":["../../../../../src/solvers/instant-open/instant-open/adapters/enigma-instant-open.ts"],"sourcesContent":["import { SymmError } from \"../../../../shared/errors/symm-error\";\nimport {\n encodeAddMarginToNextVA,\n encodeSendQuote,\n encodeSendQuoteWithAffiliateAndData,\n getFakeSendQuoteMuonSignature,\n sendQuoteUpnlSigFlexRange,\n} from \"../../shared/calldata\";\nimport { sendInstantOpen } from \"../../shared/hedger-api\";\nimport { buildSignedOperation, signAndFormatInstantOperation } from \"../../shared/operations\";\nimport { ORDER_TYPE_MARKET, isolationTypeForSide } from \"../../shared/types\";\nimport type { EnigmaInstantOpenResult, InstantOpenParameters } from \"../types\";\nimport type { InstantOpenAdapterContext } from \"./context\";\n\n/**\n * Submit an instant open to an **Enigma** (lowcap) hedger.\n *\n * Signs two operations — `addMarginToNextVA` on the AccountLayer and\n * `sendQuote` on the diamond — and posts both to `/instant_trade/instant_open`.\n *\n * The quote carries a **placeholder** Muon signature: lowcap bypasses Muon\n * verification, but the contract still reads `upnlSig.price`, and the encoded\n * signature region is delegated to the solver via a `FlexField` so it can write a\n * live attestation at execution time. Only the `sendQuote` operation carries the\n * delegation; `addMargin` stays fully fixed.\n *\n * @throws {SymmError} `INSTANT_OPEN_MARGIN_REQUIRED` when `margin` is absent —\n * reachable when the caller omitted `solverId` and the chain's default solver\n * turned out to be Enigma.\n * @throws {SymmApiError} when the hedger request fails.\n * @internal\n */\nexport async function submitEnigmaInstantOpen(\n context: InstantOpenAdapterContext,\n parameters: InstantOpenParameters,\n): Promise<EnigmaInstantOpenResult> {\n if (!parameters.margin) {\n throw new SymmError(\n \"validation\",\n \"INSTANT_OPEN_MARGIN_REQUIRED\",\n \"instantOpen: the Enigma (lowcap) flow funds a new virtual account, so `margin.amount` is required.\",\n );\n }\n\n const { config, solver, chainConfig, walletClient, signerAddress, deadline, symbolId, metadata } = context;\n const { accountLayerAddress, symmioAddress, affiliatesAddress } = chainConfig.addresses;\n\n const addMarginCallData = encodeAddMarginToNextVA({\n subAccount: parameters.subAccountAddress,\n isolationType: isolationTypeForSide(parameters.positionType),\n symbolId,\n amount: parameters.margin.amount,\n });\n\n const quoteArgs = {\n partyBsWhiteList: [solver.address],\n symbolId,\n positionType: parameters.positionType,\n orderType: ORDER_TYPE_MARKET,\n price: parameters.order.price,\n quantity: parameters.order.quantity,\n cva: parameters.lockedParam.cva,\n lf: parameters.lockedParam.lf,\n partyAmm: parameters.lockedParam.partyAmm,\n partyBmm: parameters.lockedParam.partyBmm,\n deadline,\n affiliate: affiliatesAddress,\n data: metadata,\n upnlSig: getFakeSendQuoteMuonSignature(parameters.markPrice ?? parameters.order.price),\n };\n\n /**\n * Which quote-send call to sign is a chain-generation fact: a v0.8.5 diamond\n * has no capped `sendQuote` selector (the calldata would revert), and a\n * v0.8.6 solver rejects the legacy call's zero fee caps.\n */\n const sendQuoteCallData =\n chainConfig.contractsVersion === \"0.8.5\"\n ? encodeSendQuoteWithAffiliateAndData(quoteArgs)\n : encodeSendQuote({ ...quoteArgs, solverFeeCaps: parameters.solverFeeCaps });\n\n const addMarginOp = buildSignedOperation({\n signer: signerAddress,\n target: accountLayerAddress,\n callData: addMarginCallData,\n signerAccount: parameters.subAccountAddress,\n deadline: parameters.operationDeadline ?? deadline,\n salt: parameters.addMarginSalt,\n });\n\n const sendQuoteOp = buildSignedOperation({\n signer: signerAddress,\n target: symmioAddress,\n callData: sendQuoteCallData,\n signerAccount: parameters.subAccountAddress,\n deadline: parameters.operationDeadline ?? deadline,\n salt: parameters.sendQuoteSalt,\n flexFields: [{ ...sendQuoteUpnlSigFlexRange(sendQuoteCallData), authorizedFlexFiller: solver.address }],\n });\n\n const [addMargin, sendQuote] = await Promise.all([\n signAndFormatInstantOperation(config, { operation: addMarginOp, chainId: context.chainId, walletClient }),\n signAndFormatInstantOperation(config, { operation: sendQuoteOp, chainId: context.chainId, walletClient }),\n ]);\n\n const response = await sendInstantOpen(config, {\n chainId: context.chainId,\n // The resolved solver's own id — never a hardcoded kind, so a differently-id'd\n // solver of the same kind can never be re-resolved onto the wrong endpoint.\n solverId: solver.id,\n request: { addMargin, sendQuote },\n });\n\n return {\n kind: \"enigma\",\n success: true,\n tempQuoteId:\n response.temp_quote_id !== undefined && response.temp_quote_id !== null\n ? String(response.temp_quote_id)\n : undefined,\n partyBmm: response.partyBmm,\n };\n}\n"],"mappings":";;;;;;AAgCA,eAAsB,EACpB,GACA,GACkC;CAClC,IAAI,CAAC,EAAW,QACd,MAAM,IAAI,EACR,cACA,gCACA,oGACF;CAGF,IAAM,EAAE,WAAQ,WAAQ,gBAAa,iBAAc,kBAAe,aAAU,aAAU,gBAAa,GAC7F,EAAE,wBAAqB,kBAAe,yBAAsB,EAAY,WAExE,IAAoB,EAAwB;EAChD,YAAY,EAAW;EACvB,eAAe,EAAqB,EAAW,YAAY;EAC3D;EACA,QAAQ,EAAW,OAAO;CAC5B,CAAC,GAEK,IAAY;EAChB,kBAAkB,CAAC,EAAO,OAAO;EACjC;EACA,cAAc,EAAW;EACzB,WAAA;EACA,OAAO,EAAW,MAAM;EACxB,UAAU,EAAW,MAAM;EAC3B,KAAK,EAAW,YAAY;EAC5B,IAAI,EAAW,YAAY;EAC3B,UAAU,EAAW,YAAY;EACjC,UAAU,EAAW,YAAY;EACjC;EACA,WAAW;EACX,MAAM;EACN,SAAS,EAA8B,EAAW,aAAa,EAAW,MAAM,KAAK;CACvF,GAOM,IACJ,EAAY,qBAAqB,UAC7B,EAAoC,CAAS,IAC7C,EAAgB;EAAE,GAAG;EAAW,eAAe,EAAW;CAAc,CAAC,GAEzE,IAAc,EAAqB;EACvC,QAAQ;EACR,QAAQ;EACR,UAAU;EACV,eAAe,EAAW;EAC1B,UAAU,EAAW,qBAAqB;EAC1C,MAAM,EAAW;CACnB,CAAC,GAEK,IAAc,EAAqB;EACvC,QAAQ;EACR,QAAQ;EACR,UAAU;EACV,eAAe,EAAW;EAC1B,UAAU,EAAW,qBAAqB;EAC1C,MAAM,EAAW;EACjB,YAAY,CAAC;GAAE,GAAG,EAA0B,CAAiB;GAAG,sBAAsB,EAAO;EAAQ,CAAC;CACxG,CAAC,GAEK,CAAC,GAAW,KAAa,MAAM,QAAQ,IAAI,CAC/C,EAA8B,GAAQ;EAAE,WAAW;EAAa,SAAS,EAAQ;EAAS;CAAa,CAAC,GACxG,EAA8B,GAAQ;EAAE,WAAW;EAAa,SAAS,EAAQ;EAAS;CAAa,CAAC,CAC1G,CAAC,GAEK,IAAW,MAAM,EAAgB,GAAQ;EAC7C,SAAS,EAAQ;EAGjB,UAAU,EAAO;EACjB,SAAS;GAAE;GAAW;EAAU;CAClC,CAAC;CAED,OAAO;EACL,MAAM;EACN,SAAS;EACT,aACE,EAAS,kBAAkB,KAAA,KAAa,EAAS,kBAAkB,OAC/D,OAAO,EAAS,aAAa,IAC7B,KAAA;EACN,UAAU,EAAS;CACrB;AACF"}
@@ -31,6 +31,8 @@ export type InstantOpenParameters<K extends SymmioSolverKind = SymmioSolverKind>
31
31
  orderType?: SolverOrderType;
32
32
  /** Order-side values (`price`, `quantity`) — both 18-decimal-wei `bigint`. */
33
33
  order: InstantOpenOrder;
34
+ /** Mark price for the lowcap Muon placeholder, in 18-decimal wei. Defaults to order.price. */
35
+ markPrice?: bigint;
34
36
  /** Locked-margin breakdown (`cva`, `lf`, `partyAmm`, `partyBmm`) — all 18-decimal-wei `bigint`. */
35
37
  lockedParam: InstantOpenLockedParams;
36
38
  /**
@@ -60,6 +62,8 @@ export type InstantOpenParameters<K extends SymmioSolverKind = SymmioSolverKind>
60
62
  sendQuoteSalt?: Hex;
61
63
  /** Override the unix-seconds deadline (defaults to `now + 300s`). */
62
64
  deadline?: bigint;
65
+ /** Lowcap signed-operation expiry in unix seconds. Defaults to the quote deadline. */
66
+ operationDeadline?: bigint;
63
67
  }>;
64
68
  /** Fields both solver kinds return from a successful instant open. */
65
69
  interface BaseInstantOpenResult {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/instant-open/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,OAAO,CACxF,gBAAgB,GACd,aAAa,GAAG;IACd,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,CAAC;IACb,wFAAwF;IACxF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,8EAA8E;IAC9E,KAAK,EAAE,gBAAgB,CAAC;IACxB,mGAAmG;IACnG,WAAW,EAAE,uBAAuB,CAAC;IACrC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,sEAAsE;IACtE,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CACJ,CAAC;AAEF,sEAAsE;AACtE,UAAU,qBAAqB;IAC7B,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mEAAmE;AACnE,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,mDAAmD;IACnD,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,qBAAsB,SAAQ,qBAAqB;IAClE,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,GAAG,EAAE,eAAe,CAAC;CACtB;AAED,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,uBAAuB,CAAC;IAChC,IAAI,EAAE,qBAAqB,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,uBAAuB,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/instant-open/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,OAAO,CACxF,gBAAgB,GACd,aAAa,GAAG;IACd,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,CAAC;IACb,wFAAwF;IACxF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,8EAA8E;IAC9E,KAAK,EAAE,gBAAgB,CAAC;IACxB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mGAAmG;IACnG,WAAW,EAAE,uBAAuB,CAAC;IACrC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,sEAAsE;IACtE,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CACJ,CAAC;AAEF,sEAAsE;AACtE,UAAU,qBAAqB;IAC7B,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mEAAmE;AACnE,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,mDAAmD;IACnD,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,qBAAsB,SAAQ,qBAAqB;IAClE,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,GAAG,EAAE,eAAe,CAAC;CACtB;AAED,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,uBAAuB,CAAC;IAChC,IAAI,EAAE,qBAAqB,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,uBAAuB,CAAC,CAAC,CAAC,CAAC"}
@@ -12,10 +12,10 @@ import { PrepareInstantOpenParameters } from '../prepare-instant-open-params/pre
12
12
  *
13
13
  * @example
14
14
  * ```ts
15
- * const { tempQuoteId } = await instantOpenAuto(config, {
16
- * subAccountAddress, sessionKeyAddress, signTypedData,
17
- * marketId: 1, positionType: "LONG",
18
- * userInput: "100", leverage: 5, slippage: 1,
15
+ * const result = await instantOpenAuto(config, {
16
+ * subAccountAddress, from: sessionKeyAddress,
17
+ * market: { id: 1 }, positionType: PositionType.LONG,
18
+ * fund: { mode: "full-balance", balance: "100" }, leverage: 5, slippage: 1,
19
19
  * });
20
20
  * ```
21
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"instant-open-auto.js","names":[],"sources":["../../../../src/solvers/instant-open/instant-open-auto/instant-open-auto.ts"],"sourcesContent":["import type { Config } from \"../../../core/config\";\nimport { instantOpen } from \"../instant-open/instant-open\";\nimport type { InstantOpenReturnType } from \"../instant-open/types\";\nimport {\n prepareInstantOpenParams,\n type PrepareInstantOpenParameters,\n} from \"../prepare-instant-open-params/prepare-instant-open-params\";\n\n/**\n * Resolve missing inputs via {@link prepareInstantOpenParams} and immediately\n * submit through {@link instantOpen}.\n *\n * Friendly default for callers that have the trade intent and trust the SDK\n * to fetch the rest. For full control — inspect / mutate resolved params\n * between fetch and submit — call `prepareInstantOpenParams` + `instantOpen`\n * separately.\n *\n * @example\n * ```ts\n * const { tempQuoteId } = await instantOpenAuto(config, {\n * subAccountAddress, sessionKeyAddress, signTypedData,\n * marketId: 1, positionType: \"LONG\",\n * userInput: \"100\", leverage: 5, slippage: 1,\n * });\n * ```\n */\nexport async function instantOpenAuto(\n config: Config,\n parameters: PrepareInstantOpenParameters,\n): Promise<InstantOpenReturnType> {\n const resolved = await prepareInstantOpenParams(config, parameters);\n return instantOpen(config, resolved);\n}\n"],"mappings":";;;AA0BA,eAAsB,EACpB,GACA,GACgC;CAEhC,OAAO,EAAY,GAAQ,MADJ,EAAyB,GAAQ,CAAU,CAC/B;AACrC"}
1
+ {"version":3,"file":"instant-open-auto.js","names":[],"sources":["../../../../src/solvers/instant-open/instant-open-auto/instant-open-auto.ts"],"sourcesContent":["import type { Config } from \"../../../core/config\";\nimport { instantOpen } from \"../instant-open/instant-open\";\nimport type { InstantOpenReturnType } from \"../instant-open/types\";\nimport {\n prepareInstantOpenParams,\n type PrepareInstantOpenParameters,\n} from \"../prepare-instant-open-params/prepare-instant-open-params\";\n\n/**\n * Resolve missing inputs via {@link prepareInstantOpenParams} and immediately\n * submit through {@link instantOpen}.\n *\n * Friendly default for callers that have the trade intent and trust the SDK\n * to fetch the rest. For full control — inspect / mutate resolved params\n * between fetch and submit — call `prepareInstantOpenParams` + `instantOpen`\n * separately.\n *\n * @example\n * ```ts\n * const result = await instantOpenAuto(config, {\n * subAccountAddress, from: sessionKeyAddress,\n * market: { id: 1 }, positionType: PositionType.LONG,\n * fund: { mode: \"full-balance\", balance: \"100\" }, leverage: 5, slippage: 1,\n * });\n * ```\n */\nexport async function instantOpenAuto(\n config: Config,\n parameters: PrepareInstantOpenParameters,\n): Promise<InstantOpenReturnType> {\n const resolved = await prepareInstantOpenParams(config, parameters);\n return instantOpen(config, resolved);\n}\n"],"mappings":";;;AA0BA,eAAsB,EACpB,GACA,GACgC;CAEhC,OAAO,EAAY,GAAQ,MADJ,EAAyB,GAAQ,CAAU,CAC/B;AACrC"}
@@ -32,7 +32,7 @@ import { InstantOpenMarketData, PositionType } from '../shared/types.js';
32
32
  export interface FullBalanceFunding {
33
33
  /** Discriminant selecting the full-balance sizing path. */
34
34
  mode: "full-balance";
35
- /** The entire collateral to move into the VA, as a USD decimal string. */
35
+ /** Fee-inclusive funding budget to move into the VA, in USD. */
36
36
  balance: string;
37
37
  }
38
38
  /**
@@ -66,6 +66,8 @@ type PrepareInstantOpenBaseParameters = WriteSolverParameter & {
66
66
  * omitted) the auto-slippage derivation.
67
67
  */
68
68
  estimatedOpenPrice?: string | null;
69
+ /** Optional estimate arrival time in epoch milliseconds. Accepted for compatibility; core does not use it. */
70
+ estimatedOpenPriceTimestamp?: number;
69
71
  /**
70
72
  * Pre-fetched solver locked params (matches `getLockedParams` return —
71
73
  * `ApiLockedParamsBySymbolIdResponse`). When supplied with all four
@@ -93,6 +95,8 @@ type PrepareInstantOpenBaseParameters = WriteSolverParameter & {
93
95
  sendQuoteSalt?: Hex;
94
96
  /** Forwarded to {@link InstantOpenParameters}. */
95
97
  deadline?: bigint;
98
+ /** Lowcap operation expiry, separate from quote expiry. Forwarded to instantOpen. */
99
+ operationDeadline?: bigint;
96
100
  };
97
101
  /**
98
102
  * Parameters for {@link prepareInstantOpenParams} and `instantOpenAuto`.
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-instant-open-params.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2DAA2D,CAAC;AAC5F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAC7F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AASnE,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AA+BhF;;;;;;GAMG;AACH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,IAAI,EAAE,cAAc,CAAC;IACrB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,KAAK,gCAAgC,GAAG,oBAAoB,GAAG;IAC7D,oCAAoC;IACpC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,uEAAuE;IACvE,MAAM,EAAE,qBAAqB,CAAC;IAC9B,kBAAkB;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,iCAAiC,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,kDAAkD;IAClD,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAChD,gCAAgC,GAAG;IACjC,sGAAsG;IACtG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC3B,CACF,CAAC;AAEF,+FAA+F;AAC/F,MAAM,MAAM,kCAAkC,GAAG,qBAAqB,GAAG;IACvE,uFAAuF;IACvF,WAAW,EAAE,gBAAgB,GAAG,cAAc,CAAC;CAChD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,4BAA4B,GACvC,OAAO,CAAC,kCAAkC,CAAC,CA+Q7C"}
1
+ {"version":3,"file":"prepare-instant-open-params.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/prepare-instant-open-params/prepare-instant-open-params.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2DAA2D,CAAC;AAC5F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAC7F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AASnE,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AA+BhF;;;;;;GAMG;AACH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,IAAI,EAAE,cAAc,CAAC;IACrB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,KAAK,gCAAgC,GAAG,oBAAoB,GAAG;IAC7D,oCAAoC;IACpC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,uEAAuE;IACvE,MAAM,EAAE,qBAAqB,CAAC;IAC9B,kBAAkB;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,8GAA8G;IAC9G,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,iCAAiC,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,kDAAkD;IAClD,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAChD,gCAAgC,GAAG;IACjC,sGAAsG;IACtG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC3B,CACF,CAAC;AAEF,+FAA+F;AAC/F,MAAM,MAAM,kCAAkC,GAAG,qBAAqB,GAAG;IACvE,uFAAuF;IACvF,WAAW,EAAE,gBAAgB,GAAG,cAAc,CAAC;CAChD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,4BAA4B,GACvC,OAAO,CAAC,kCAAkC,CAAC,CAiR7C"}
@@ -168,6 +168,7 @@ async function b(r, v) {
168
168
  subAccountAddress: v.subAccountAddress,
169
169
  marketId: v.market.id,
170
170
  positionType: v.positionType,
171
+ markPrice: n(E),
171
172
  order: {
172
173
  price: n(F.requestedOpenPrice),
173
174
  quantity: n(F.quantity)
@@ -186,7 +187,8 @@ async function b(r, v) {
186
187
  uuid: v.uuid,
187
188
  addMarginSalt: v.addMarginSalt,
188
189
  sendQuoteSalt: v.sendQuoteSalt,
189
- deadline: v.deadline
190
+ deadline: v.deadline,
191
+ operationDeadline: v.operationDeadline
190
192
  };
191
193
  }
192
194
  //#endregion
@@ -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 { 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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"}
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 /** Fee-inclusive funding budget to move into the VA, in USD. */\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 /** Optional estimate arrival time in epoch milliseconds. Accepted for compatibility; core does not use it. */\n estimatedOpenPriceTimestamp?: number;\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 /** Lowcap operation expiry, separate from quote expiry. Forwarded to instantOpen. */\n operationDeadline?: 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 markPrice: toWeiBigInt(markPrice),\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 operationDeadline: parameters.operationDeadline,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hedger-api.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/shared/hedger-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAC7C,mBAAmB,GAAG;IACpB,6FAA6F;IAC7F,OAAO,EAAE,uBAAuB,CAAC;CAClC,CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,yBAAyB,GACpC,OAAO,CAAC,yBAAyB,CAAC,CAsBpC;AAED;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,kBAAkB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,OAAO,CACjD,mBAAmB,GAAG;IACpB,8EAA8E;IAC9E,SAAS,EAAE,uBAAuB,CAAC;CACpC,CACF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,6BAA6B,GACxC,OAAO,CAAC,6BAA6B,CAAC,CAyBxC"}
1
+ {"version":3,"file":"hedger-api.d.ts","sourceRoot":"","sources":["../../../../src/solvers/instant-open/shared/hedger-api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAC7C,mBAAmB,GAAG;IACpB,6FAA6F;IAC7F,OAAO,EAAE,uBAAuB,CAAC;CAClC,CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,yBAAyB,GACpC,OAAO,CAAC,yBAAyB,CAAC,CAgDpC;AAED;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,kBAAkB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,OAAO,CACjD,mBAAmB,GAAG;IACpB,8EAA8E;IAC9E,SAAS,EAAE,uBAAuB,CAAC;CACpC,CACF,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,6BAA6B,GACxC,OAAO,CAAC,6BAA6B,CAAC,CAyBxC"}
@@ -9,7 +9,17 @@ async function a(n, a) {
9
9
  solverId: a.solverId
10
10
  });
11
11
  try {
12
- return (await r(a.request, { baseURL: o.url })).data;
12
+ let t = await r(a.request, { baseURL: o.url }), n = t.data, i = n?.successful === !1 || n?.successful === "false" || n?.error_code != null || !!n?.error_message || !!n?.error, s = n?.temp_quote_id;
13
+ if (i || s == null || !/^-?\d+$/.test(String(s)) || BigInt(s) === 0n) throw new e({
14
+ code: i ? "INSTANT_OPEN_REJECTED" : "INSTANT_OPEN_INVALID_RESPONSE",
15
+ message: n?.error_message || "The solver did not accept the instant-open request.",
16
+ status: t.status,
17
+ statusText: t.statusText,
18
+ responseData: t.data,
19
+ url: `${o.url}/instant_trade/instant_open`,
20
+ method: "POST"
21
+ });
22
+ return n;
13
23
  } catch (n) {
14
24
  throw n instanceof t ? n : i(n) ? e.fromAxios(n, {
15
25
  code: "SEND_INSTANT_OPEN_FAILED",
@@ -1 +1 @@
1
- {"version":3,"file":"hedger-api.js","names":[],"sources":["../../../../src/solvers/instant-open/shared/hedger-api.ts"],"sourcesContent":["import { isAxiosError } from \"axios\";\nimport type { Config } from \"../../../core/config\";\nimport { SymmApiError, SymmError } from \"../../../shared/errors/symm-error\";\nimport type { Compute, ReadSolverParameter } from \"../../../shared/types/properties\";\nimport {\n postInstantTradeInstantOpen,\n type ApiPostInstantOpenResponse,\n type ApiV2InstantOpenRequest,\n} from \"../../types/generated/enigma-solver\";\nimport {\n instantRequestForQuoteWithSignatureInstantTradeOpenPost,\n type InstantRFQResponse,\n type InstantOperation as RasaInstantOperation,\n} from \"../../types/generated/rasa-solver\";\nimport type { InstantOperationPayload } from \"./types\";\n\n/**\n * Response shape from the hedger's `/instant_trade/instant_open` endpoint.\n *\n * Re-exported from the orval-generated client so consumers can read the raw\n * response without importing the generated module directly.\n */\nexport type SendInstantOpenReturnType = ApiPostInstantOpenResponse;\n\n/**\n * Parameters for {@link sendInstantOpen}.\n */\nexport type SendInstantOpenParameters = Compute<\n ReadSolverParameter & {\n /** Pre-signed addMargin + sendQuote payloads (the orval `ApiV2InstantOpenRequest` shape). */\n request: ApiV2InstantOpenRequest;\n }\n>;\n\n/**\n * Submit a v2 instant open request to the chain's hedger.\n *\n * Wraps the orval-generated `postInstantTradeInstantOpen` with the chain's\n * solver/hedger base URL and SDK error wrapping.\n *\n * @throws {SymmApiError} when the hedger request fails.\n * @throws {SymmError} when the chain is unsupported.\n */\nexport async function sendInstantOpen(\n config: Config,\n parameters: SendInstantOpenParameters,\n): Promise<SendInstantOpenReturnType> {\n const solver = config.getSolver({ chainId: parameters.chainId, solverId: parameters.solverId });\n try {\n const response = await postInstantTradeInstantOpen(parameters.request, { baseURL: solver.url });\n return response.data;\n } catch (err) {\n if (err instanceof SymmError) throw err;\n\n if (isAxiosError(err)) {\n throw SymmApiError.fromAxios(err, {\n code: \"SEND_INSTANT_OPEN_FAILED\",\n baseURL: solver.url,\n });\n }\n\n throw new SymmError(\n \"api\",\n \"SEND_INSTANT_OPEN_FAILED\",\n `Failed to send instant open: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n}\n\n/**\n * Response shape from Rasa's `/instant_trade/open` endpoint — the accepted\n * request-for-quote, echoed back in full.\n */\nexport type SendRasaInstantOpenReturnType = InstantRFQResponse;\n\n/**\n * Parameters for {@link sendRasaInstantOpen}.\n */\nexport type SendRasaInstantOpenParameters = Compute<\n ReadSolverParameter & {\n /** The pre-signed `sendQuote` payload. Rasa's flow has no `addMargin` leg. */\n sendQuote: InstantOperationPayload;\n }\n>;\n\n/**\n * Submit a v2 instant open request to a Rasa hedger.\n *\n * Rasa is cross-margin, so the request carries only `sendQuote` — its\n * `addMargin` field is optional and deliberately omitted.\n *\n * @remarks\n * Rasa's OpenAPI spec declares `SignedOperation` **without** `flexFields` /\n * `maxUses` and with a required `nonce`, which does not match what the service\n * actually accepts — the reference implementation posts the same full payload to\n * both solvers in production. The cast below bridges that stale spec; regenerate\n * the client and drop it once the vendor publishes a corrected schema.\n *\n * @throws {SymmApiError} when the hedger request fails.\n * @throws {SymmError} when the chain or solver is unsupported.\n */\nexport async function sendRasaInstantOpen(\n config: Config,\n parameters: SendRasaInstantOpenParameters,\n): Promise<SendRasaInstantOpenReturnType> {\n const solver = config.getSolver({ chainId: parameters.chainId, solverId: parameters.solverId });\n try {\n const response = await instantRequestForQuoteWithSignatureInstantTradeOpenPost(\n { sendQuote: parameters.sendQuote as unknown as RasaInstantOperation },\n { baseURL: solver.url },\n );\n return response.data;\n } catch (err) {\n if (err instanceof SymmError) throw err;\n\n if (isAxiosError(err)) {\n throw SymmApiError.fromAxios(err, {\n code: \"SEND_RASA_INSTANT_OPEN_FAILED\",\n baseURL: solver.url,\n });\n }\n\n throw new SymmError(\n \"api\",\n \"SEND_RASA_INSTANT_OPEN_FAILED\",\n `Failed to send Rasa instant open: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n}\n"],"mappings":";;;;;AA2CA,eAAsB,EACpB,GACA,GACoC;CACpC,IAAM,IAAS,EAAO,UAAU;EAAE,SAAS,EAAW;EAAS,UAAU,EAAW;CAAS,CAAC;CAC9F,IAAI;EAEF,QAAO,MADgB,EAA4B,EAAW,SAAS,EAAE,SAAS,EAAO,IAAI,CAAC,GAC9E;CAClB,SAAS,GAAK;EAUZ,MATI,aAAe,IAAiB,IAEhC,EAAa,CAAG,IACZ,EAAa,UAAU,GAAK;GAChC,MAAM;GACN,SAAS,EAAO;EAClB,CAAC,IAGG,IAAI,EACR,OACA,4BACA,gCAAgC,aAAe,QAAQ,EAAI,UAAU,OAAO,CAAG,KAC/E,EAAE,OAAO,aAAe,QAAQ,IAAM,KAAA,EAAU,CAClD;CACF;AACF;AAkCA,eAAsB,EACpB,GACA,GACwC;CACxC,IAAM,IAAS,EAAO,UAAU;EAAE,SAAS,EAAW;EAAS,UAAU,EAAW;CAAS,CAAC;CAC9F,IAAI;EAKF,QAAO,MAJgB,EACrB,EAAE,WAAW,EAAW,UAA6C,GACrE,EAAE,SAAS,EAAO,IAAI,CACxB,GACgB;CAClB,SAAS,GAAK;EAUZ,MATI,aAAe,IAAiB,IAEhC,EAAa,CAAG,IACZ,EAAa,UAAU,GAAK;GAChC,MAAM;GACN,SAAS,EAAO;EAClB,CAAC,IAGG,IAAI,EACR,OACA,iCACA,qCAAqC,aAAe,QAAQ,EAAI,UAAU,OAAO,CAAG,KACpF,EAAE,OAAO,aAAe,QAAQ,IAAM,KAAA,EAAU,CAClD;CACF;AACF"}
1
+ {"version":3,"file":"hedger-api.js","names":[],"sources":["../../../../src/solvers/instant-open/shared/hedger-api.ts"],"sourcesContent":["import { isAxiosError } from \"axios\";\nimport type { Config } from \"../../../core/config\";\nimport { SymmApiError, SymmError } from \"../../../shared/errors/symm-error\";\nimport type { Compute, ReadSolverParameter } from \"../../../shared/types/properties\";\nimport {\n postInstantTradeInstantOpen,\n type ApiPostInstantOpenResponse,\n type ApiV2InstantOpenRequest,\n} from \"../../types/generated/enigma-solver\";\nimport {\n instantRequestForQuoteWithSignatureInstantTradeOpenPost,\n type InstantRFQResponse,\n type InstantOperation as RasaInstantOperation,\n} from \"../../types/generated/rasa-solver\";\nimport type { InstantOperationPayload } from \"./types\";\n\n/**\n * Response shape from the hedger's `/instant_trade/instant_open` endpoint.\n *\n * Re-exported from the orval-generated client so consumers can read the raw\n * response without importing the generated module directly.\n */\nexport type SendInstantOpenReturnType = ApiPostInstantOpenResponse;\n\n/**\n * Parameters for {@link sendInstantOpen}.\n */\nexport type SendInstantOpenParameters = Compute<\n ReadSolverParameter & {\n /** Pre-signed addMargin + sendQuote payloads (the orval `ApiV2InstantOpenRequest` shape). */\n request: ApiV2InstantOpenRequest;\n }\n>;\n\n/**\n * Submit a v2 instant open request to the chain's hedger.\n *\n * Wraps the orval-generated `postInstantTradeInstantOpen` with the chain's\n * solver/hedger base URL and SDK error wrapping.\n *\n * @throws {SymmApiError} when the hedger request fails.\n * @throws {SymmError} when the chain is unsupported.\n */\nexport async function sendInstantOpen(\n config: Config,\n parameters: SendInstantOpenParameters,\n): Promise<SendInstantOpenReturnType> {\n const solver = config.getSolver({ chainId: parameters.chainId, solverId: parameters.solverId });\n try {\n const response = await postInstantTradeInstantOpen(parameters.request, { baseURL: solver.url });\n // Business rejections can arrive with HTTP 200; the generated success type\n // does not describe those bodies. Never report acceptance without an id.\n const body = response.data as ApiPostInstantOpenResponse & {\n successful?: boolean | string;\n error_code?: unknown;\n error_message?: string;\n error?: unknown;\n };\n const rejected =\n body?.successful === false ||\n body?.successful === \"false\" ||\n body?.error_code != null ||\n !!body?.error_message ||\n !!body?.error;\n const id = body?.temp_quote_id;\n if (rejected || id == null || !/^-?\\d+$/.test(String(id)) || BigInt(id) === 0n) {\n throw new SymmApiError({\n code: rejected ? \"INSTANT_OPEN_REJECTED\" : \"INSTANT_OPEN_INVALID_RESPONSE\",\n message: body?.error_message || \"The solver did not accept the instant-open request.\",\n status: response.status,\n statusText: response.statusText,\n responseData: response.data,\n url: `${solver.url}/instant_trade/instant_open`,\n method: \"POST\",\n });\n }\n return body;\n } catch (err) {\n if (err instanceof SymmError) throw err;\n\n if (isAxiosError(err)) {\n throw SymmApiError.fromAxios(err, {\n code: \"SEND_INSTANT_OPEN_FAILED\",\n baseURL: solver.url,\n });\n }\n\n throw new SymmError(\n \"api\",\n \"SEND_INSTANT_OPEN_FAILED\",\n `Failed to send instant open: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n}\n\n/**\n * Response shape from Rasa's `/instant_trade/open` endpoint — the accepted\n * request-for-quote, echoed back in full.\n */\nexport type SendRasaInstantOpenReturnType = InstantRFQResponse;\n\n/**\n * Parameters for {@link sendRasaInstantOpen}.\n */\nexport type SendRasaInstantOpenParameters = Compute<\n ReadSolverParameter & {\n /** The pre-signed `sendQuote` payload. Rasa's flow has no `addMargin` leg. */\n sendQuote: InstantOperationPayload;\n }\n>;\n\n/**\n * Submit a v2 instant open request to a Rasa hedger.\n *\n * Rasa is cross-margin, so the request carries only `sendQuote` — its\n * `addMargin` field is optional and deliberately omitted.\n *\n * @remarks\n * Rasa's OpenAPI spec declares `SignedOperation` **without** `flexFields` /\n * `maxUses` and with a required `nonce`, which does not match what the service\n * actually accepts — the reference implementation posts the same full payload to\n * both solvers in production. The cast below bridges that stale spec; regenerate\n * the client and drop it once the vendor publishes a corrected schema.\n *\n * @throws {SymmApiError} when the hedger request fails.\n * @throws {SymmError} when the chain or solver is unsupported.\n */\nexport async function sendRasaInstantOpen(\n config: Config,\n parameters: SendRasaInstantOpenParameters,\n): Promise<SendRasaInstantOpenReturnType> {\n const solver = config.getSolver({ chainId: parameters.chainId, solverId: parameters.solverId });\n try {\n const response = await instantRequestForQuoteWithSignatureInstantTradeOpenPost(\n { sendQuote: parameters.sendQuote as unknown as RasaInstantOperation },\n { baseURL: solver.url },\n );\n return response.data;\n } catch (err) {\n if (err instanceof SymmError) throw err;\n\n if (isAxiosError(err)) {\n throw SymmApiError.fromAxios(err, {\n code: \"SEND_RASA_INSTANT_OPEN_FAILED\",\n baseURL: solver.url,\n });\n }\n\n throw new SymmError(\n \"api\",\n \"SEND_RASA_INSTANT_OPEN_FAILED\",\n `Failed to send Rasa instant open: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err instanceof Error ? err : undefined },\n );\n }\n}\n"],"mappings":";;;;;AA2CA,eAAsB,EACpB,GACA,GACoC;CACpC,IAAM,IAAS,EAAO,UAAU;EAAE,SAAS,EAAW;EAAS,UAAU,EAAW;CAAS,CAAC;CAC9F,IAAI;EACF,IAAM,IAAW,MAAM,EAA4B,EAAW,SAAS,EAAE,SAAS,EAAO,IAAI,CAAC,GAGxF,IAAO,EAAS,MAMhB,IACJ,GAAM,eAAe,MACrB,GAAM,eAAe,WACrB,GAAM,cAAc,QACpB,CAAC,CAAC,GAAM,iBACR,CAAC,CAAC,GAAM,OACJ,IAAK,GAAM;EACjB,IAAI,KAAY,KAAM,QAAQ,CAAC,UAAU,KAAK,OAAO,CAAE,CAAC,KAAK,OAAO,CAAE,MAAM,IAC1E,MAAM,IAAI,EAAa;GACrB,MAAM,IAAW,0BAA0B;GAC3C,SAAS,GAAM,iBAAiB;GAChC,QAAQ,EAAS;GACjB,YAAY,EAAS;GACrB,cAAc,EAAS;GACvB,KAAK,GAAG,EAAO,IAAI;GACnB,QAAQ;EACV,CAAC;EAEH,OAAO;CACT,SAAS,GAAK;EAUZ,MATI,aAAe,IAAiB,IAEhC,EAAa,CAAG,IACZ,EAAa,UAAU,GAAK;GAChC,MAAM;GACN,SAAS,EAAO;EAClB,CAAC,IAGG,IAAI,EACR,OACA,4BACA,gCAAgC,aAAe,QAAQ,EAAI,UAAU,OAAO,CAAG,KAC/E,EAAE,OAAO,aAAe,QAAQ,IAAM,KAAA,EAAU,CAClD;CACF;AACF;AAkCA,eAAsB,EACpB,GACA,GACwC;CACxC,IAAM,IAAS,EAAO,UAAU;EAAE,SAAS,EAAW;EAAS,UAAU,EAAW;CAAS,CAAC;CAC9F,IAAI;EAKF,QAAO,MAJgB,EACrB,EAAE,WAAW,EAAW,UAA6C,GACrE,EAAE,SAAS,EAAO,IAAI,CACxB,GACgB;CAClB,SAAS,GAAK;EAUZ,MATI,aAAe,IAAiB,IAEhC,EAAa,CAAG,IACZ,EAAa,UAAU,GAAK;GAChC,MAAM;GACN,SAAS,EAAO;EAClB,CAAC,IAGG,IAAI,EACR,OACA,iCACA,qCAAqC,aAAe,QAAQ,EAAI,UAAU,OAAO,CAAG,KACpF,EAAE,OAAO,aAAe,QAAQ,IAAM,KAAA,EAAU,CAClD;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symmio/trading-core",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "Framework-agnostic SYMMIO SDK. Contract calls, calculations, and transformations with no framework assumptions.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/SYMM-IO/Trading-SDK/tree/main/packages/trading-core#readme",