@rhea-finance/confidential-swap 0.2.7 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -604,6 +604,18 @@ function record(value) {
604
604
  responseAssert(value && typeof value === "object" && !Array.isArray(value), "Expected an object response.");
605
605
  return value;
606
606
  }
607
+ function httpErrorMessage(data, status, content) {
608
+ if (data && typeof data === "object" && !Array.isArray(data)) {
609
+ const body = data;
610
+ const apiMessage = [body.message, body.error, body.msg].find(
611
+ (value) => typeof value === "string" && value.trim()
612
+ );
613
+ if (typeof apiMessage === "string") return apiMessage.trim();
614
+ }
615
+ const trimmed = content.trim();
616
+ if (trimmed && !trimmed.startsWith("<") && trimmed.length <= 300) return trimmed;
617
+ return `Service request failed (${status}).`;
618
+ }
607
619
  var HttpConfidentialApi = class {
608
620
  constructor(config) {
609
621
  this.config = config;
@@ -652,7 +664,13 @@ var HttpConfidentialApi = class {
652
664
  } catch {
653
665
  throw new ConfidentialSwapError("INVALID_RESPONSE", "Service returned invalid JSON.", response.status);
654
666
  }
655
- if (!response.ok) throw new ConfidentialSwapError(response.status === 401 || response.status === 403 ? "UNAUTHORIZED" : "HTTP_ERROR", `Service request failed (${response.status}).`, response.status);
667
+ if (!response.ok) {
668
+ throw new ConfidentialSwapError(
669
+ response.status === 401 || response.status === 403 ? "UNAUTHORIZED" : "HTTP_ERROR",
670
+ httpErrorMessage(data, response.status, content),
671
+ response.status
672
+ );
673
+ }
656
674
  return data;
657
675
  } catch (error) {
658
676
  throwIfAborted(signal);
@@ -969,6 +987,13 @@ var SessionManager = class {
969
987
  };
970
988
 
971
989
  // src/quote.ts
990
+ var MAX_FLEX_FUNDING_REQUOTES = 3;
991
+ function assertFundingQuoteWithinSlippage(baselineMinOut, nextAmountOut) {
992
+ assert(
993
+ nextAmountOut >= baselineMinOut,
994
+ "Funding quote moved beyond max slippage."
995
+ );
996
+ }
972
997
  function aggregateWithdrawalAppFee(quotes, assetId) {
973
998
  if (quotes.length === 0 || quotes.some((quote) => !quote.quoteRequest?.amount || !Array.isArray(quote.quoteRequest.appFees))) return void 0;
974
999
  let totalInput = 0n;
@@ -1030,23 +1055,42 @@ async function quoteDepositAndWithdrawals(params) {
1030
1055
  slippageBps: req.slippageBps
1031
1056
  };
1032
1057
  const initialSwapQuote = await deps.swap.quote(clone(swapRequest), signal);
1033
- raw(initialSwapQuote.amountOut);
1034
- assert(raw(initialSwapQuote.minAmountOut) <= raw(initialSwapQuote.amountOut), "Invalid funding swap minimum output.");
1035
- depositQuote = await deps.api.quote({
1036
- ...base,
1037
- amount: initialSwapQuote.amountOut,
1038
- refundTo: signerId,
1039
- refundType: "CONFIDENTIAL_INTENTS",
1040
- depositType: "ORIGIN_CHAIN",
1041
- swapType: "FLEX_INPUT",
1042
- dry: false
1043
- }, signal);
1044
- validateQuote(depositQuote, true);
1045
- swapRequest = { ...swapRequest, recipient: depositQuote.quote.depositAddress };
1046
- swapQuote = await deps.swap.quote(clone(swapRequest), signal);
1047
- raw(swapQuote.amountOut);
1048
- assert(raw(swapQuote.minAmountOut) <= raw(swapQuote.amountOut), "Invalid funding swap minimum output.");
1049
- fundingAmount = swapQuote.amountOut;
1058
+ const baselineOut = raw(initialSwapQuote.amountOut);
1059
+ const baselineMinOut = raw(initialSwapQuote.minAmountOut);
1060
+ assert(baselineMinOut <= baselineOut, "Invalid funding swap minimum output.");
1061
+ let latestDepositAmountIn = initialSwapQuote.amountOut;
1062
+ let covered = false;
1063
+ for (let attempt = 0; attempt < MAX_FLEX_FUNDING_REQUOTES; attempt++) {
1064
+ depositQuote = await deps.api.quote({
1065
+ ...base,
1066
+ // Always the most recent funding-swap amountOut — never stick on pass 1
1067
+ // after a requote.
1068
+ amount: latestDepositAmountIn,
1069
+ refundTo: signerId,
1070
+ refundType: "CONFIDENTIAL_INTENTS",
1071
+ depositType: "ORIGIN_CHAIN",
1072
+ swapType: "FLEX_INPUT",
1073
+ dry: false
1074
+ }, signal);
1075
+ validateQuote(depositQuote, true);
1076
+ swapRequest = { ...swapRequest, recipient: depositQuote.quote.depositAddress };
1077
+ swapQuote = await deps.swap.quote(clone(swapRequest), signal);
1078
+ const nextOut = raw(swapQuote.amountOut);
1079
+ const nextMinOut = raw(swapQuote.minAmountOut);
1080
+ assert(nextMinOut <= nextOut, "Invalid funding swap minimum output.");
1081
+ assertFundingQuoteWithinSlippage(baselineMinOut, nextOut);
1082
+ const flexMinIn = depositQuote.quote.minAmountIn !== void 0 ? raw(depositQuote.quote.minAmountIn) : void 0;
1083
+ if (flexMinIn === void 0 || nextMinOut >= flexMinIn) {
1084
+ fundingAmount = swapQuote.amountOut;
1085
+ covered = true;
1086
+ break;
1087
+ }
1088
+ latestDepositAmountIn = swapQuote.amountOut;
1089
+ }
1090
+ assert(
1091
+ covered && swapQuote,
1092
+ "Final funding quote does not cover FLEX minimum input."
1093
+ );
1050
1094
  }
1051
1095
  }
1052
1096
  const shares = splitConfidentialRawAmount(fundingAmount, req.recipients.length, randomValues);