@stableflow/bridges 3.1.1-rc-d5f36a0408-20260723 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,9 +29,9 @@ For HTTP-only quote/status without wallet orchestration, [`@stableflow/core`](..
29
29
  | `ServiceMap` | Per-service `quote` / `send` / `getStatus` implementations |
30
30
  | `getQuoteModes` | Helpers to interpret quote shape (OneClick, exact output, etc.) |
31
31
  | Utilities | `formatQuoteError`, `addressToBytes32`, `quoteSignature`, `formatNumber` |
32
- | USDT0 / FraxZero | `USDT0_CONFIG`, `OFT_ABI`, `getHopMsgFee`, `FRAXZERO_MIDDLE_TOKEN_*`, … |
32
+ | USDT0 / FraxZero / CCTP hybrid | `USDT0_CONFIG`, `OFT_ABI`, `getHopMsgFee`, `FRAXZERO_MIDDLE_TOKEN_*`, `CCTP_MIDDLE_TOKEN_CHAIN`, `CCTP_PROXY_RELAY_CONTRACT`, … |
33
33
 
34
- Supported `Service` values (from `@stableflow/core`): `oneclick`, `usdt0`, `cctp`, `fraxzero`, composite routes (`usdt0-oneclick`, `oneclick-usdt0`, `fraxzero-oneclick`, `oneclick-fraxzero`), and `native`.
34
+ Supported `Service` values (from `@stableflow/core`): `oneclick`, `usdt0`, `cctp`, `fraxzero`, composite routes (`usdt0-oneclick`, `oneclick-usdt0`, `cctp-oneclick`, `oneclick-cctp`, `fraxzero-oneclick`, `oneclick-fraxzero`), and `native`.
35
35
 
36
36
  See `dist/index.d.ts` after `pnpm build`.
37
37
 
package/dist/index.d.mts CHANGED
@@ -147,6 +147,8 @@ interface GetAllQuoteParams {
147
147
  }[];
148
148
  swapType?: OneClickSwapType;
149
149
  isProxy?: boolean;
150
+ /** When true (default), always calculate destination gas fee. When false, fee is 0 if fromTokenSymbol !== toTokenSymbol. */
151
+ forceCalculateFee?: boolean;
150
152
  };
151
153
  }
152
154
  /**
@@ -230,10 +232,7 @@ declare const formatQuoteError: (error: any, options: {
230
232
  service: Service;
231
233
  fromToken: TokenConfig;
232
234
  }) => {
233
- serviceType: "oneclick";
234
- error: string;
235
- } | {
236
- serviceType: "usdt0" | "cctp" | "fraxzero" | "fraxzero-oneclick" | "oneclick-fraxzero" | "usdt0-oneclick" | "oneclick-usdt0" | "native";
235
+ serviceType: Service;
237
236
  error: any;
238
237
  };
239
238
 
@@ -324,4 +323,8 @@ declare const OFT_ABI: ({
324
323
  declare const FRAXZERO_MIDDLE_TOKEN_USDC: _stableflow_core.TokenConfig;
325
324
  declare const FRAXZERO_MIDDLE_TOKEN_FRXUSD: _stableflow_core.TokenConfig;
326
325
 
327
- export { BridgeSFA, type BuildTransactionResult, DATA_HEX_PROTOBUF_EXTRA, type EvmTxData, FRAXZERO_MIDDLE_TOKEN_FRXUSD, FRAXZERO_MIDDLE_TOKEN_USDC, type GetAllQuoteParams, LZ_RECEIVE_VALUE, OFT_ABI, type PermitSignature, type PermitTypedData, SIGNATURE_SIZE, ServiceMap, USDT0_CONFIG, USDT0_LEGACY_MESH_TRANSFTER_FEE, addressToBytes32, buildApproveTx, buildPermitTypedData, buildSendTx, formatNumber, formatQuoteError, getHopMsgFee, getQuoteModes, quoteSignature };
326
+ declare const MIDDLE_TOKEN_CHAIN: _stableflow_core.TokenConfig;
327
+ declare const CCTP_PROXY_RELAY_CONTRACT = "0x0da5336C5CEb9d15e7659Ae376CC41d86Edd8802";
328
+ declare const MIDDLE_CHAIN_REFOUND_ADDRESS = "0x654E7B96E1DE0b54E53D9ae8082fC2219E66dAC3";
329
+
330
+ export { BridgeSFA, type BuildTransactionResult, MIDDLE_CHAIN_REFOUND_ADDRESS as CCTP_MIDDLE_CHAIN_REFOUND_ADDRESS, MIDDLE_TOKEN_CHAIN as CCTP_MIDDLE_TOKEN_CHAIN, CCTP_PROXY_RELAY_CONTRACT, DATA_HEX_PROTOBUF_EXTRA, type EvmTxData, FRAXZERO_MIDDLE_TOKEN_FRXUSD, FRAXZERO_MIDDLE_TOKEN_USDC, type GetAllQuoteParams, LZ_RECEIVE_VALUE, OFT_ABI, type PermitSignature, type PermitTypedData, SIGNATURE_SIZE, ServiceMap, USDT0_CONFIG, USDT0_LEGACY_MESH_TRANSFTER_FEE, addressToBytes32, buildApproveTx, buildPermitTypedData, buildSendTx, formatNumber, formatQuoteError, getHopMsgFee, getQuoteModes, quoteSignature };
package/dist/index.d.ts CHANGED
@@ -147,6 +147,8 @@ interface GetAllQuoteParams {
147
147
  }[];
148
148
  swapType?: OneClickSwapType;
149
149
  isProxy?: boolean;
150
+ /** When true (default), always calculate destination gas fee. When false, fee is 0 if fromTokenSymbol !== toTokenSymbol. */
151
+ forceCalculateFee?: boolean;
150
152
  };
151
153
  }
152
154
  /**
@@ -230,10 +232,7 @@ declare const formatQuoteError: (error: any, options: {
230
232
  service: Service;
231
233
  fromToken: TokenConfig;
232
234
  }) => {
233
- serviceType: "oneclick";
234
- error: string;
235
- } | {
236
- serviceType: "usdt0" | "cctp" | "fraxzero" | "fraxzero-oneclick" | "oneclick-fraxzero" | "usdt0-oneclick" | "oneclick-usdt0" | "native";
235
+ serviceType: Service;
237
236
  error: any;
238
237
  };
239
238
 
@@ -324,4 +323,8 @@ declare const OFT_ABI: ({
324
323
  declare const FRAXZERO_MIDDLE_TOKEN_USDC: _stableflow_core.TokenConfig;
325
324
  declare const FRAXZERO_MIDDLE_TOKEN_FRXUSD: _stableflow_core.TokenConfig;
326
325
 
327
- export { BridgeSFA, type BuildTransactionResult, DATA_HEX_PROTOBUF_EXTRA, type EvmTxData, FRAXZERO_MIDDLE_TOKEN_FRXUSD, FRAXZERO_MIDDLE_TOKEN_USDC, type GetAllQuoteParams, LZ_RECEIVE_VALUE, OFT_ABI, type PermitSignature, type PermitTypedData, SIGNATURE_SIZE, ServiceMap, USDT0_CONFIG, USDT0_LEGACY_MESH_TRANSFTER_FEE, addressToBytes32, buildApproveTx, buildPermitTypedData, buildSendTx, formatNumber, formatQuoteError, getHopMsgFee, getQuoteModes, quoteSignature };
326
+ declare const MIDDLE_TOKEN_CHAIN: _stableflow_core.TokenConfig;
327
+ declare const CCTP_PROXY_RELAY_CONTRACT = "0x0da5336C5CEb9d15e7659Ae376CC41d86Edd8802";
328
+ declare const MIDDLE_CHAIN_REFOUND_ADDRESS = "0x654E7B96E1DE0b54E53D9ae8082fC2219E66dAC3";
329
+
330
+ export { BridgeSFA, type BuildTransactionResult, MIDDLE_CHAIN_REFOUND_ADDRESS as CCTP_MIDDLE_CHAIN_REFOUND_ADDRESS, MIDDLE_TOKEN_CHAIN as CCTP_MIDDLE_TOKEN_CHAIN, CCTP_PROXY_RELAY_CONTRACT, DATA_HEX_PROTOBUF_EXTRA, type EvmTxData, FRAXZERO_MIDDLE_TOKEN_FRXUSD, FRAXZERO_MIDDLE_TOKEN_USDC, type GetAllQuoteParams, LZ_RECEIVE_VALUE, OFT_ABI, type PermitSignature, type PermitTypedData, SIGNATURE_SIZE, ServiceMap, USDT0_CONFIG, USDT0_LEGACY_MESH_TRANSFTER_FEE, addressToBytes32, buildApproveTx, buildPermitTypedData, buildSendTx, formatNumber, formatQuoteError, getHopMsgFee, getQuoteModes, quoteSignature };
package/dist/index.js CHANGED
@@ -91,7 +91,7 @@ var OneClickService = class {
91
91
  }
92
92
  async formatQuoteData(res) {
93
93
  const { params } = res;
94
- const { isProxy = true, prices } = params;
94
+ const { isProxy = true, prices, forceCalculateFee = true } = params;
95
95
  const isExactOutput = params.swapType === core.OneClickSwapType.Output;
96
96
  core.getPrice(prices, params.fromToken.nativeToken.symbol);
97
97
  params.fromToken.nativeToken.decimals;
@@ -136,7 +136,7 @@ var OneClickService = class {
136
136
  }
137
137
  let destinationGasFee = Big__default.default(netFee).minus(bridgeFeeValue);
138
138
  destinationGasFee = Big__default.default(destinationGasFee).lt(0) ? Big__default.default(0) : destinationGasFee;
139
- if (fromTokenSymbol !== toTokenSymbol) {
139
+ if (!forceCalculateFee && fromTokenSymbol !== toTokenSymbol) {
140
140
  destinationGasFee = Big__default.default(0);
141
141
  }
142
142
  res.data.fees = {
@@ -164,8 +164,6 @@ var OneClickService = class {
164
164
  fromToken: params.fromToken,
165
165
  refundTo: params.refundTo,
166
166
  recipient: params.recipient,
167
- // EXACT_OUTPUT: deposit/approve amountIn (with slippage buffer) so the
168
- // first step cannot fail due to slippage; excess is refunded to refundTo.
169
167
  amountWei: isExactOutput ? res.data?.quote?.amountIn : params.amountWei,
170
168
  prices: params.prices,
171
169
  evmGasFees: params.evmGasFees,
@@ -506,7 +504,7 @@ var getQuoteModes = (params) => {
506
504
  if (typeof quoteDataService === "undefined") {
507
505
  return false;
508
506
  }
509
- if ([core.Service.OneClickUsdt0].includes(quoteDataService)) {
507
+ if ([core.Service.OneClickUsdt0, core.Service.OneClickCCTP].includes(quoteDataService)) {
510
508
  return true;
511
509
  }
512
510
  if (quoteDataService === core.Service.OneClickFraxZero) {
@@ -522,7 +520,7 @@ var getQuoteModes = (params) => {
522
520
  if (typeof quoteDataService === "undefined") {
523
521
  return false;
524
522
  }
525
- if ([core.Service.OneClickUsdt0, core.Service.OneClick].includes(quoteDataService)) {
523
+ if ([core.Service.OneClickUsdt0, core.Service.OneClick, core.Service.OneClickCCTP].includes(quoteDataService)) {
526
524
  return true;
527
525
  }
528
526
  if (quoteDataService === core.Service.OneClickFraxZero) {
@@ -538,7 +536,7 @@ var getQuoteModes = (params) => {
538
536
  if (typeof quoteDataService === "undefined") {
539
537
  return false;
540
538
  }
541
- if ([core.Service.Usdt0OneClick].includes(quoteDataService)) {
539
+ if ([core.Service.Usdt0OneClick, core.Service.CCTPOneClick].includes(quoteDataService)) {
542
540
  return true;
543
541
  }
544
542
  if (quoteDataService === core.Service.FraxZeroOneClick) {
@@ -554,7 +552,7 @@ var getQuoteModes = (params) => {
554
552
  isExactOutput: getIsExactOutput(),
555
553
  isOneClickService: getIsOneClickService(),
556
554
  isQuoteParamDepositAddress: getIsQuoteParamDepositAddress(),
557
- isPermitWithNonce: typeof quoteDataService === "undefined" ? false : [core.Service.OneClickUsdt0, core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(quoteDataService)
555
+ isPermitWithNonce: typeof quoteDataService === "undefined" ? false : [core.Service.OneClickUsdt0, core.Service.OneClickCCTP, core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(quoteDataService)
558
556
  };
559
557
  };
560
558
  function zeroPadValue(hex, lengthBytes) {
@@ -737,46 +735,6 @@ function parseUserFriendlyTonAddress(address) {
737
735
  isTestOnly
738
736
  };
739
737
  }
740
- var formatQuoteError = (error, options) => {
741
- const { service, fromToken } = options;
742
- const defaultErrorMessage = "Failed to get quote, please try again later";
743
- if (service === core.Service.OneClick) {
744
- const getQuoteErrorMessage = () => {
745
- const _messageResult = {
746
- message: error?.message || defaultErrorMessage,
747
- sourceMessage: error?.response?.data?.message || defaultErrorMessage
748
- };
749
- if (error?.response?.data?.message && error?.response?.data?.message !== "Internal server error") {
750
- if (error?.response?.data?.message === "Failed to get quote") {
751
- _messageResult.message = "Amount exceeds max";
752
- return _messageResult;
753
- }
754
- if (error?.response?.data?.message?.includes("Amount is too low for bridge, try at least")) {
755
- const match = error.response.data.message.match(/try at least\s+(\d+(?:\.\d+)?)/i);
756
- let minimumAmount = match ? match[1] : Big__default.default(1).times(10 ** fromToken.decimals).toFixed(0);
757
- minimumAmount = Big__default.default(minimumAmount).div(10 ** fromToken.decimals).toFixed(fromToken.decimals);
758
- _messageResult.message = `Amount is too low, at least ${minimumAmount}`;
759
- return _messageResult;
760
- }
761
- return _messageResult;
762
- }
763
- return _messageResult;
764
- };
765
- const onclickErrMsg = getQuoteErrorMessage();
766
- return {
767
- serviceType: service,
768
- error: onclickErrMsg.message
769
- };
770
- }
771
- return {
772
- serviceType: service,
773
- error: error?.message || defaultErrorMessage
774
- };
775
- };
776
- async function quoteSignature(params) {
777
- const response = await core.postRequest("/v0/cctp/sign", params);
778
- return response.data ?? {};
779
- }
780
738
  var addThousandSeparator = (numberString) => {
781
739
  if (!numberString) return "0";
782
740
  const parts = String(numberString).split(".");
@@ -880,6 +838,54 @@ var formatNumber = (value, precision, isSimple, options) => {
880
838
  };
881
839
  };
882
840
 
841
+ // src/utils/error.ts
842
+ var formatQuoteError = (error, options) => {
843
+ const { service, fromToken } = options;
844
+ const defaultErrorMessage = "Failed to get quote, please try again later";
845
+ if ([core.Service.OneClick, core.Service.OneClickUsdt0, core.Service.Usdt0OneClick, core.Service.CCTPOneClick, core.Service.OneClickCCTP, core.Service.FraxZeroOneClick, core.Service.OneClickFraxZero].includes(service)) {
846
+ const getQuoteErrorMessage = () => {
847
+ const apiMessage = error?.body?.message || error?.response?.data?.message;
848
+ const _messageResult = {
849
+ message: error?.message || defaultErrorMessage,
850
+ sourceMessage: apiMessage || defaultErrorMessage
851
+ };
852
+ if (apiMessage && apiMessage !== "Internal server error") {
853
+ if (apiMessage === "Failed to get quote") {
854
+ _messageResult.message = "Amount exceeds max";
855
+ return _messageResult;
856
+ }
857
+ if (apiMessage.includes("Amount is too low for bridge, try at least")) {
858
+ const match = apiMessage.match(/try at least\s+(\d+(?:\.\d+)?)/i);
859
+ const minWei = match ? match[1] : Big__default.default(1).times(10 ** fromToken.decimals).toFixed(0);
860
+ const minAmount = Big__default.default(minWei).div(10 ** fromToken.decimals);
861
+ const readableAmount = formatNumber(minAmount, fromToken.decimals, true);
862
+ _messageResult.message = `Amount is too low, at least ${readableAmount} ${fromToken.symbol}`;
863
+ return _messageResult;
864
+ }
865
+ if (apiMessage.includes("Cannot convert undefined or null to object")) {
866
+ _messageResult.message = "app fees exceeds 5% of amount";
867
+ return _messageResult;
868
+ }
869
+ return _messageResult;
870
+ }
871
+ return _messageResult;
872
+ };
873
+ const onclickErrMsg = getQuoteErrorMessage();
874
+ return {
875
+ serviceType: service,
876
+ error: onclickErrMsg.message
877
+ };
878
+ }
879
+ return {
880
+ serviceType: service,
881
+ error: error?.message || defaultErrorMessage
882
+ };
883
+ };
884
+ async function quoteSignature(params) {
885
+ const response = await core.postRequest("/v0/cctp/sign", params);
886
+ return response.data ?? {};
887
+ }
888
+
883
889
  // src/usdt0/config.ts
884
890
  var USDT0_CONFIG = {
885
891
  Ethereum: {
@@ -4041,8 +4047,9 @@ var CCTP_TOKEN_PROXY_ABI = [
4041
4047
  "type": "function"
4042
4048
  }
4043
4049
  ];
4044
-
4045
- // src/cctp/config.ts
4050
+ var MIDDLE_TOKEN_CHAIN2 = core.usdcChains["arb"];
4051
+ var CCTP_PROXY_RELAY_CONTRACT = "0x0da5336C5CEb9d15e7659Ae376CC41d86Edd8802";
4052
+ var MIDDLE_CHAIN_REFOUND_ADDRESS2 = "0x654E7B96E1DE0b54E53D9ae8082fC2219E66dAC3";
4046
4053
  var CCTP_DOMAINS = {
4047
4054
  Ethereum: 0,
4048
4055
  Arbitrum: 3,
@@ -5546,6 +5553,279 @@ var OneClickUsdt0Service = class {
5546
5553
  }
5547
5554
  };
5548
5555
  var from_oneclick_default2 = new OneClickUsdt0Service();
5556
+ var excludeFees5 = ["estimateGasUsd"];
5557
+ var CCTPOneClickService = class {
5558
+ async quote(params) {
5559
+ const {
5560
+ dry,
5561
+ evmWallet,
5562
+ evmAddress
5563
+ } = params;
5564
+ const cs = new core.Csl(core.OpenAPI.DEBUG);
5565
+ const csl = cs.log;
5566
+ const execTime = new core.ExecTime({ type: "CCTPOneClickService", logStyle: "lime-700", isDebug: core.OpenAPI.DEBUG });
5567
+ if (!evmWallet) {
5568
+ throw new Error("evmWallet is required");
5569
+ }
5570
+ if (!evmAddress) {
5571
+ throw new Error("evmAddress is required");
5572
+ }
5573
+ const cctpParams = {
5574
+ ...params,
5575
+ toToken: MIDDLE_TOKEN_CHAIN2,
5576
+ destinationChain: MIDDLE_TOKEN_CHAIN2.chainName,
5577
+ recipient: MIDDLE_CHAIN_REFOUND_ADDRESS2
5578
+ };
5579
+ const oneClickParams = {
5580
+ ...params,
5581
+ fromToken: MIDDLE_TOKEN_CHAIN2,
5582
+ originAsset: MIDDLE_TOKEN_CHAIN2.assetId,
5583
+ swapType: core.OneClickSwapType.Flex,
5584
+ isProxy: false,
5585
+ refundTo: evmAddress,
5586
+ wallet: evmWallet
5587
+ };
5588
+ let cctpResult;
5589
+ let oneClickResult;
5590
+ if (!dry) {
5591
+ execTime.breakpoint();
5592
+ oneClickResult = await oneclick_default.quote({
5593
+ ...oneClickParams,
5594
+ amountWei: Big__default.default(0.01).times(10 ** MIDDLE_TOKEN_CHAIN2.decimals).toFixed(0, 0)
5595
+ });
5596
+ execTime.log("CCTPOneClickService.quote", "oneClickService.quote: %o", oneClickResult);
5597
+ if (oneClickResult.errMsg) {
5598
+ return oneClickResult;
5599
+ }
5600
+ cctpParams.recipient = oneClickResult.quote.depositAddress;
5601
+ execTime.breakpoint();
5602
+ cctpResult = await cctp_default.quote(cctpParams);
5603
+ execTime.log("CCTPOneClickService.quote", "cctpService.quote: %o", cctpResult);
5604
+ execTime.breakpoint();
5605
+ try {
5606
+ const oneClickResult2 = await oneclick_default.quote({
5607
+ ...oneClickParams,
5608
+ dry: true,
5609
+ amountWei: Big__default.default(cctpResult.outputAmount || 0).times(10 ** MIDDLE_TOKEN_CHAIN2.decimals).toFixed(0, 0)
5610
+ });
5611
+ oneClickResult.fees = oneClickResult2.fees;
5612
+ oneClickResult.outputAmount = oneClickResult2.outputAmount;
5613
+ oneClickResult.estimateTime = oneClickResult2.estimateTime;
5614
+ oneClickResult.priceImpact = oneClickResult2.priceImpact;
5615
+ oneClickResult.exchangeRate = oneClickResult2.exchangeRate;
5616
+ execTime.log("CCTPOneClickService.quote", "confirm get actual output amount result: %o", oneClickResult2);
5617
+ } catch (err) {
5618
+ execTime.log("CCTPOneClickService.quote", "confirm get actual output amount error: %o", err);
5619
+ }
5620
+ } else {
5621
+ execTime.breakpoint();
5622
+ cctpResult = await cctp_default.quote(cctpParams);
5623
+ execTime.log("CCTPOneClickService.quote", "cctpService.quote dry: %o", cctpResult);
5624
+ if (cctpResult.errMsg) {
5625
+ return cctpResult;
5626
+ }
5627
+ oneClickParams.amountWei = Big__default.default(cctpResult.outputAmount || 0).times(10 ** MIDDLE_TOKEN_CHAIN2.decimals).toFixed(0, 0);
5628
+ execTime.breakpoint();
5629
+ oneClickResult = await oneclick_default.quote(oneClickParams);
5630
+ execTime.log("CCTPOneClickService.quote", "oneClickService.quote: %o", oneClickResult);
5631
+ }
5632
+ if (oneClickResult.errMsg) {
5633
+ return oneClickResult;
5634
+ }
5635
+ if (cctpResult.errMsg) {
5636
+ return cctpResult;
5637
+ }
5638
+ csl("CCTPOneClickService quote", "rose-600", "oneClickResult: %o", oneClickResult);
5639
+ csl("CCTPOneClickService quote", "rose-600", "cctpResult: %o", cctpResult);
5640
+ let totalFeesUsd = Big__default.default(0);
5641
+ const fees = {
5642
+ ...cctpResult.fees
5643
+ };
5644
+ for (const feeKey in oneClickResult.fees) {
5645
+ if (excludeFees.includes(feeKey)) {
5646
+ continue;
5647
+ }
5648
+ fees[feeKey] = oneClickResult.fees[feeKey];
5649
+ }
5650
+ for (const feeKey in fees) {
5651
+ if (excludeFees5.includes(feeKey)) {
5652
+ continue;
5653
+ }
5654
+ totalFeesUsd = Big__default.default(totalFeesUsd || 0).plus(fees[feeKey] || 0);
5655
+ }
5656
+ execTime.logTotal("CCTPOneClickService.quote");
5657
+ return {
5658
+ ...cctpResult,
5659
+ fees,
5660
+ totalFeesUsd: core.numberRemoveEndZero(Big__default.default(totalFeesUsd).toFixed(20)),
5661
+ estimateTime: cctpResult.estimateTime + oneClickResult.estimateTime,
5662
+ outputAmount: oneClickResult.outputAmount,
5663
+ priceImpact: oneClickResult.priceImpact,
5664
+ exchangeRate: oneClickResult.exchangeRate,
5665
+ quoteParam: {
5666
+ ...cctpResult.quoteParam,
5667
+ toToken: params.toToken,
5668
+ middleToken: MIDDLE_TOKEN_CHAIN2,
5669
+ recipient: params.recipient,
5670
+ depositAddress: oneClickResult.quote.depositAddress
5671
+ },
5672
+ sourceQuoteParams: params
5673
+ };
5674
+ }
5675
+ async estimateTransaction(params, quoteData) {
5676
+ return cctp_default.estimateTransaction(params, quoteData);
5677
+ }
5678
+ async send(params) {
5679
+ const {
5680
+ wallet,
5681
+ ...rest
5682
+ } = params;
5683
+ return wallet.send(core.SendType.SEND, rest);
5684
+ }
5685
+ getStatus(params) {
5686
+ return core.getRequest("/v0/trade", {
5687
+ deposit_address: params.depositAddress
5688
+ });
5689
+ }
5690
+ };
5691
+ var to_oneclick_default3 = new CCTPOneClickService();
5692
+ var OneClickCCTPService = class {
5693
+ async quote(params) {
5694
+ const {
5695
+ evmWallet,
5696
+ evmAddress,
5697
+ fromToken,
5698
+ prices
5699
+ } = params;
5700
+ const execTime = new core.ExecTime({ type: "OneClickCCTP", logStyle: "lime-500", isDebug: core.OpenAPI.DEBUG });
5701
+ if (!evmWallet) {
5702
+ throw new Error("evmWallet is required");
5703
+ }
5704
+ if (!evmAddress) {
5705
+ throw new Error("evmAddress is required");
5706
+ }
5707
+ let secondStepAmountWei = Big__default.default(params.amountWei || 0).div(10 ** fromToken.decimals).times(10 ** MIDDLE_TOKEN_CHAIN2.decimals).toFixed(0);
5708
+ if (!core.isStableToken(fromToken)) {
5709
+ const inputPrice = core.getPrice(prices, fromToken.symbol);
5710
+ const inputValue = Big__default.default(params.amountWei || 0).div(10 ** fromToken.decimals).times(inputPrice);
5711
+ secondStepAmountWei = Big__default.default(inputValue).times(10 ** MIDDLE_TOKEN_CHAIN2.decimals).toFixed(0);
5712
+ }
5713
+ const cctpParams = {
5714
+ ...params,
5715
+ amountWei: secondStepAmountWei,
5716
+ fromToken: MIDDLE_TOKEN_CHAIN2,
5717
+ originChain: MIDDLE_TOKEN_CHAIN2.chainName,
5718
+ refundTo: MIDDLE_CHAIN_REFOUND_ADDRESS2,
5719
+ wallet: evmWallet
5720
+ };
5721
+ execTime.breakpoint();
5722
+ const cctpResult = await cctp_default.quote(cctpParams);
5723
+ execTime.log("cctpService.quote");
5724
+ const cctpFeeBuffer = 1.2;
5725
+ const cctpMintFeeUsd = core.numberRemoveEndZero(Big__default.default(cctpResult.fees?.estimateMintGasUsd || 0).times(1 + cctpFeeBuffer).toFixed(20));
5726
+ const cctpBridgeFeeUsd = core.numberRemoveEndZero(Big__default.default(cctpResult.fees?.bridgeFeeUsd || 0).times(1 + cctpFeeBuffer).toFixed(20));
5727
+ const cctpTotalFeeUsd = Big__default.default(cctpMintFeeUsd || 0).plus(cctpBridgeFeeUsd || 0).toFixed(20);
5728
+ if (cctpResult.errMsg) {
5729
+ return cctpResult;
5730
+ }
5731
+ const cctpFeeAmountInFromToken = Big__default.default(cctpTotalFeeUsd || 0).div(core.getPrice(prices, fromToken.symbol) || 1).toFixed(fromToken.decimals);
5732
+ const fromTokenAmount = Big__default.default(params.amountWei).div(10 ** fromToken.decimals).toFixed(fromToken.decimals);
5733
+ const oneClickFeeRatio = Big__default.default(cctpFeeAmountInFromToken || 0).div(Big__default.default(cctpFeeAmountInFromToken || 0).plus(fromTokenAmount)).times(1e4).toFixed(0, Big__default.default.roundUp);
5734
+ if (Big__default.default(oneClickFeeRatio).gt(1e4)) {
5735
+ return { errMsg: `Amount is too low, at least ${cctpFeeAmountInFromToken}` };
5736
+ }
5737
+ execTime.breakpoint();
5738
+ const oneClickResult = await oneclick_default.quote({
5739
+ ...params,
5740
+ amountWei: secondStepAmountWei,
5741
+ toToken: MIDDLE_TOKEN_CHAIN2,
5742
+ destinationAsset: MIDDLE_TOKEN_CHAIN2.assetId,
5743
+ swapType: core.OneClickSwapType.Output,
5744
+ isProxy: true,
5745
+ recipient: evmAddress,
5746
+ appFees: [
5747
+ ...params.appFees || [],
5748
+ {
5749
+ recipient: "reffer.near",
5750
+ fee: +oneClickFeeRatio
5751
+ }
5752
+ ]
5753
+ });
5754
+ execTime.log("oneClickService.quote");
5755
+ let totalFeesUsd = Big__default.default(0);
5756
+ let _destinationGasFeeUsd = Big__default.default(oneClickResult.fees?.destinationGasFeeUsd || 0).minus(cctpTotalFeeUsd);
5757
+ if (Big__default.default(_destinationGasFeeUsd).lt(0)) {
5758
+ _destinationGasFeeUsd = Big__default.default(0);
5759
+ }
5760
+ const fees = {
5761
+ ...oneClickResult.fees,
5762
+ destinationGasFeeUsd: core.numberRemoveEndZero(Big__default.default(_destinationGasFeeUsd).toFixed(20)),
5763
+ estimateMintGasUsd: cctpMintFeeUsd,
5764
+ bridgeFeeUsd: cctpBridgeFeeUsd
5765
+ };
5766
+ for (const feeKey in cctpResult.fees) {
5767
+ if (["estimateGasUsd"].includes(feeKey)) {
5768
+ continue;
5769
+ }
5770
+ if (!fees[feeKey]) {
5771
+ fees[feeKey] = cctpResult.fees[feeKey];
5772
+ }
5773
+ }
5774
+ for (const feeKey in fees) {
5775
+ if (excludeFees.includes(feeKey)) {
5776
+ continue;
5777
+ }
5778
+ totalFeesUsd = Big__default.default(totalFeesUsd || 0).plus(fees[feeKey] || 0);
5779
+ }
5780
+ const cctpSendParam = cctpResult.sendParam?.param;
5781
+ execTime.log("OneClickCCTPService.quote");
5782
+ return {
5783
+ ...oneClickResult,
5784
+ needPermit: true,
5785
+ permitSpender: CCTP_PROXY_RELAY_CONTRACT,
5786
+ permitToken: MIDDLE_TOKEN_CHAIN2,
5787
+ permitAmountWei: oneClickResult?.quote?.amountOut,
5788
+ permitAdditionalData: {
5789
+ amount_wei: cctpSendParam?.[0]?.toString(),
5790
+ charged_amount: cctpSendParam?.[1]?.toString(),
5791
+ destination_domain: cctpSendParam?.[2]?.toString(),
5792
+ mint_recipient: cctpParams.recipient,
5793
+ burn_token: cctpSendParam?.[4]?.toString(),
5794
+ destination_caller: cctpSendParam?.[5]?.toString(),
5795
+ max_fee: cctpSendParam?.[6]?.toString(),
5796
+ finality_threshold: cctpSendParam?.[7]?.toString(),
5797
+ receipt_address: params.recipient,
5798
+ source_domain: cctpResult.quoteParam?.sourceDomain,
5799
+ destination_domain_id: cctpResult.quoteParam?.destinationDomain
5800
+ },
5801
+ fees,
5802
+ totalFeesUsd: core.numberRemoveEndZero(Big__default.default(totalFeesUsd).toFixed(20)),
5803
+ estimateTime: cctpResult.estimateTime + oneClickResult.estimateTime,
5804
+ outputAmount: cctpResult.outputAmount,
5805
+ needCreateTokenAccount: cctpResult.needCreateTokenAccount,
5806
+ quoteParam: {
5807
+ ...oneClickResult.quoteParam,
5808
+ toToken: params.toToken,
5809
+ middleToken: MIDDLE_TOKEN_CHAIN2,
5810
+ recipient: params.recipient
5811
+ },
5812
+ cctpSendParam,
5813
+ sourceQuoteParams: params
5814
+ };
5815
+ }
5816
+ async estimateTransaction(params, quoteData) {
5817
+ return oneclick_default.estimateTransaction(params, quoteData);
5818
+ }
5819
+ async send(params) {
5820
+ return oneclick_default.send(params);
5821
+ }
5822
+ getStatus(params) {
5823
+ return core.getRequest("/v0/trade", {
5824
+ deposit_address: params.depositAddress
5825
+ });
5826
+ }
5827
+ };
5828
+ var from_oneclick_default3 = new OneClickCCTPService();
5549
5829
 
5550
5830
  // src/native/contract.ts
5551
5831
  var NativeChains = {
@@ -5712,6 +5992,8 @@ var ServiceMap = {
5712
5992
  [core.Service.OneClickFraxZero]: from_oneclick_default,
5713
5993
  [core.Service.Usdt0OneClick]: to_oneclick_default2,
5714
5994
  [core.Service.OneClickUsdt0]: from_oneclick_default2,
5995
+ [core.Service.CCTPOneClick]: to_oneclick_default3,
5996
+ [core.Service.OneClickCCTP]: from_oneclick_default3,
5715
5997
  [core.Service.Native]: native_default
5716
5998
  };
5717
5999
  var OVERRIDE_KEYS = /* @__PURE__ */ new Set([
@@ -5963,6 +6245,8 @@ var BridgeSFA = class _BridgeSFA {
5963
6245
  core.Service.OneClick,
5964
6246
  core.Service.Usdt0OneClick,
5965
6247
  core.Service.OneClickUsdt0,
6248
+ core.Service.CCTPOneClick,
6249
+ core.Service.OneClickCCTP,
5966
6250
  core.Service.FraxZeroOneClick,
5967
6251
  core.Service.OneClickFraxZero
5968
6252
  ].includes(service)) {
@@ -5972,12 +6256,15 @@ var BridgeSFA = class _BridgeSFA {
5972
6256
  _params.appFees = params.oneclickParams?.appFees || params.appFees;
5973
6257
  _params.swapType = params.oneclickParams?.swapType;
5974
6258
  _params.isProxy = params.oneclickParams?.isProxy;
6259
+ _params.forceCalculateFee = params.oneclickParams?.forceCalculateFee;
5975
6260
  }
5976
6261
  if ([
5977
6262
  core.Service.Usdt0,
5978
6263
  core.Service.CCTP,
5979
6264
  core.Service.Usdt0OneClick,
5980
- core.Service.OneClickUsdt0
6265
+ core.Service.OneClickUsdt0,
6266
+ core.Service.CCTPOneClick,
6267
+ core.Service.OneClickCCTP
5981
6268
  ].includes(service)) {
5982
6269
  _params.originChain = params.fromToken.chainName;
5983
6270
  _params.destinationChain = params.toToken.chainName;
@@ -5991,6 +6278,8 @@ var BridgeSFA = class _BridgeSFA {
5991
6278
  }
5992
6279
  const isFromUsdt = ["USDT", "USD\u20AE0"].includes(fromToken.symbol);
5993
6280
  const isToUsdt = ["USDT", "USD\u20AE0"].includes(toToken.symbol);
6281
+ const isFromUsdc = ["USDC"].includes(fromToken.symbol);
6282
+ const isToUsdc = ["USDC"].includes(toToken.symbol);
5994
6283
  const quoteServices = [];
5995
6284
  const pushQuoteService = (_service) => {
5996
6285
  const serviceStatus = core.getRouteStatus(_service, disabledServices);
@@ -6035,6 +6324,24 @@ var BridgeSFA = class _BridgeSFA {
6035
6324
  if (fromToken.services.includes(core.Service.OneClick) && toToken.services.includes(core.Service.FraxZero)) {
6036
6325
  pushQuoteService(core.Service.OneClickFraxZero);
6037
6326
  }
6327
+ if (fromToken.services.includes(core.Service.CCTP) && toToken.services.includes(core.Service.OneClick) && fromToken.chainName !== "Arbitrum") {
6328
+ if (isFromUsdc && isToUsdc) {
6329
+ if (toToken.chainName !== "Arbitrum") {
6330
+ pushQuoteService(core.Service.CCTPOneClick);
6331
+ }
6332
+ } else {
6333
+ pushQuoteService(core.Service.CCTPOneClick);
6334
+ }
6335
+ }
6336
+ if (fromToken.services.includes(core.Service.OneClick) && toToken.services.includes(core.Service.CCTP) && toToken.chainName !== "Arbitrum") {
6337
+ if (isFromUsdc && isToUsdc) {
6338
+ if (fromToken.chainName !== "Arbitrum") {
6339
+ pushQuoteService(core.Service.OneClickCCTP);
6340
+ }
6341
+ } else {
6342
+ pushQuoteService(core.Service.OneClickCCTP);
6343
+ }
6344
+ }
6038
6345
  if (params.singleService) {
6039
6346
  const quoteService = quoteServices.find((service) => service.service === params.singleService);
6040
6347
  if (quoteService) {
@@ -6165,6 +6472,12 @@ var BridgeSFA = class _BridgeSFA {
6165
6472
  ...quote.permitAdditionalData
6166
6473
  };
6167
6474
  }
6475
+ if ([core.Service.OneClickCCTP].includes(serviceType)) {
6476
+ reportData.cctp_permit = {
6477
+ ...permitSignature,
6478
+ ...quote.permitAdditionalData
6479
+ };
6480
+ }
6168
6481
  if ([core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(serviceType)) {
6169
6482
  reportData.frax_zero_permit = {
6170
6483
  ...permitSignature,
@@ -6320,7 +6633,7 @@ var BridgeSFA = class _BridgeSFA {
6320
6633
  result.status = core.TransactionStatus.Failed;
6321
6634
  }
6322
6635
  }
6323
- if ([core.Service.OneClickUsdt0, core.Service.Usdt0OneClick, core.Service.FraxZero, core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(serviceType)) {
6636
+ if ([core.Service.OneClickUsdt0, core.Service.Usdt0OneClick, core.Service.CCTPOneClick, core.Service.OneClickCCTP, core.Service.FraxZero, core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(serviceType)) {
6324
6637
  const _result = response?.data;
6325
6638
  const status = _result?.status;
6326
6639
  if (status === core.StableflowStatus.SUCCESS) {
@@ -6368,6 +6681,9 @@ var getHopMsgFee = async (params) => {
6368
6681
  };
6369
6682
 
6370
6683
  exports.BridgeSFA = BridgeSFA;
6684
+ exports.CCTP_MIDDLE_CHAIN_REFOUND_ADDRESS = MIDDLE_CHAIN_REFOUND_ADDRESS2;
6685
+ exports.CCTP_MIDDLE_TOKEN_CHAIN = MIDDLE_TOKEN_CHAIN2;
6686
+ exports.CCTP_PROXY_RELAY_CONTRACT = CCTP_PROXY_RELAY_CONTRACT;
6371
6687
  exports.DATA_HEX_PROTOBUF_EXTRA = DATA_HEX_PROTOBUF_EXTRA;
6372
6688
  exports.FRAXZERO_MIDDLE_TOKEN_FRXUSD = FRAXZERO_MIDDLE_TOKEN_FRXUSD;
6373
6689
  exports.FRAXZERO_MIDDLE_TOKEN_USDC = FRAXZERO_MIDDLE_TOKEN_USDC;