@silentswap/react 0.0.49 → 0.0.51

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.
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { type Connector } from 'wagmi';
3
3
  import { type WalletClient } from 'viem';
4
- import { ENVIRONMENT, type SilentSwapClient, type SilentSwapClientConfig, type AuthResponse, type QuoteResponse } from '@silentswap/sdk';
4
+ import { ENVIRONMENT, type SilentSwapClient, type SilentSwapClientConfig, type AuthResponse, type QuoteResponse, type CalculationDirection } from '@silentswap/sdk';
5
5
  import { type ExecuteSwapParams, type SwapResult } from '../hooks/silent/useSilentQuote.js';
6
6
  import { type OutputStatus } from '../hooks/silent/useOrderTracking.js';
7
7
  import { type SolanaWalletConnector, type SolanaConnection } from '../hooks/silent/solana-transaction.js';
@@ -37,7 +37,7 @@ export interface SilentSwapContextType {
37
37
  serviceFeeRate: number;
38
38
  overheadUsd: number;
39
39
  egressEstimatesLoading: boolean;
40
- fetchEstimates: (direction?: 'input-to-output' | 'output-to-input') => Promise<void>;
40
+ fetchEstimates: (direction?: CalculationDirection) => Promise<void>;
41
41
  handleNewSwap: () => void;
42
42
  solanaRpcUrl?: string;
43
43
  }
@@ -35,7 +35,9 @@ export function useOrderSigning(walletClient, connector, client, setCurrentStep,
35
35
  if (!connector) {
36
36
  throw new Error('Connector required for chain switching');
37
37
  }
38
- await ensureChain(NI_CHAIN_ID_AVALANCHE, walletClient, connector);
38
+ if (isDepositingDirectly) {
39
+ await ensureChain(NI_CHAIN_ID_AVALANCHE, walletClient, connector);
40
+ }
39
41
  return Promise.all(authorizations.map(async (auth) => ({
40
42
  ...auth,
41
43
  signature: await (async () => {
@@ -1,4 +1,4 @@
1
- import { BridgeProvider, type AssetInfo } from '@silentswap/sdk';
1
+ import { BridgeProvider, type AssetInfo, type CalculationDirection } from '@silentswap/sdk';
2
2
  import type { Destination } from './useSwap.js';
3
3
  export interface UseEgressEstimatesOptions {
4
4
  evmAddress: `0x${string}` | string | undefined;
@@ -10,7 +10,7 @@ export interface UseEgressEstimatesOptions {
10
10
  updateDestinationAmount: (index: number, amount: string) => void;
11
11
  serviceFeeRate?: number;
12
12
  overheadUsd?: number;
13
- calculationDirection?: 'input-to-output' | 'output-to-input';
13
+ calculationDirection?: CalculationDirection;
14
14
  setInputAmount?: (amount: string) => void;
15
15
  }
16
16
  /**
@@ -18,7 +18,7 @@ export interface UseEgressEstimatesOptions {
18
18
  * Matches the behavior of Svelte Form.svelte's fetch_live_estimate()
19
19
  */
20
20
  export declare function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmount, destinations, splits, updateDestinationAmount, serviceFeeRate, overheadUsd, calculationDirection, setInputAmount, }: UseEgressEstimatesOptions): {
21
- fetchEstimates: (direction?: "input-to-output" | "output-to-input") => Promise<any>;
21
+ fetchEstimates: (direction?: CalculationDirection) => Promise<any>;
22
22
  isLoading: boolean;
23
23
  error: Error | null;
24
24
  egressRates: number[];
@@ -1,13 +1,13 @@
1
1
  import { useState, useCallback, useRef, useMemo } from 'react';
2
2
  import { BigNumber } from 'bignumber.js';
3
3
  import { useOrderEstimates } from './useOrderEstimates.js';
4
- import { getAssetByCaip19, S_CAIP19_USDC_AVALANCHE } from '@silentswap/sdk';
4
+ import { getAssetByCaip19, S_CAIP19_USDC_AVALANCHE, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from '@silentswap/sdk';
5
5
  import { usePrices } from './usePrices.js';
6
6
  /**
7
7
  * Hook to fetch egress estimates and calculate accurate output amounts
8
8
  * Matches the behavior of Svelte Form.svelte's fetch_live_estimate()
9
9
  */
10
- export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmount, destinations, splits, updateDestinationAmount, serviceFeeRate = 0.01, overheadUsd = 0, calculationDirection = 'input-to-output', setInputAmount, }) {
10
+ export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmount, destinations, splits, updateDestinationAmount, serviceFeeRate = 0.01, overheadUsd = 0, calculationDirection = CALCULATION_DIRECTION_INPUT_TO_OUTPUT, setInputAmount, }) {
11
11
  const { estimateOrder, isLoading, error } = useOrderEstimates({
12
12
  evmAddress: evmAddress,
13
13
  solAddress: solAddress,
@@ -26,9 +26,9 @@ export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmoun
26
26
  /**
27
27
  * Fetch egress estimates and calculate output amounts
28
28
  * This matches Svelte's fetch_live_estimate() function
29
- * @param direction - Calculation direction: 'input-to-output' (normal) or 'output-to-input' (reverse)
29
+ * @param direction - Calculation direction: CALCULATION_DIRECTION_INPUT_TO_OUTPUT (normal) or CALCULATION_DIRECTION_OUTPUT_TO_INPUT (reverse)
30
30
  */
31
- const fetchEstimates = useCallback(async (direction = 'input-to-output') => {
31
+ const fetchEstimates = useCallback(async (direction = CALCULATION_DIRECTION_INPUT_TO_OUTPUT) => {
32
32
  console.log('[EgressEstimates] Step 1: Starting fetchEstimates', { direction, tokenIn: tokenIn?.caip19, inputAmount, destinationsCount: destinations.length });
33
33
  // Validate all required inputs before proceeding
34
34
  // Note: quoteAddress is not required for estimates - useOrderEstimates uses fallback addresses when needed
@@ -75,7 +75,7 @@ export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmoun
75
75
  }
76
76
  // Fetch estimates (both ingress and egress in parallel)
77
77
  // For reverse calculation (output-to-input), pass output amounts and use EXACT_OUTPUT
78
- const effectiveDirection = direction || calculationDirection || 'input-to-output';
78
+ const effectiveDirection = direction || calculationDirection || CALCULATION_DIRECTION_INPUT_TO_OUTPUT;
79
79
  console.log('[EgressEstimates] Step 4: Calling estimateOrder', {
80
80
  effectiveDirection,
81
81
  sourceAsset: tokenIn.caip19,
@@ -83,7 +83,7 @@ export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmoun
83
83
  destinationsCount: destinationAssets.length,
84
84
  splits,
85
85
  });
86
- const requestPromise = estimateOrder(fetchedUsdcPrice || 1, tokenIn, sourcePrice, inputAmount, destinationAssets, destinationPrices, splits, effectiveDirection, effectiveDirection === 'output-to-input'
86
+ const requestPromise = estimateOrder(fetchedUsdcPrice || 1, tokenIn, sourcePrice, inputAmount, destinationAssets, destinationPrices, splits, effectiveDirection, effectiveDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT
87
87
  ? destinations.map((dest) => dest.amount) // Pass output amounts for reverse calculation
88
88
  : undefined);
89
89
  // Store the in-flight request
@@ -108,9 +108,9 @@ export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmoun
108
108
  // Calculate deposit amount in USD (matches Svelte calculation - lines 173-177)
109
109
  // Note: This is the USD value after ingress retention, not the USDC amount
110
110
  let depositUsd;
111
- // Handle reverse calculation: if direction is 'output-to-input',
111
+ // Handle reverse calculation: if direction is CALCULATION_DIRECTION_OUTPUT_TO_INPUT,
112
112
  // the estimate system calculated the required input amount
113
- if (effectiveDirection === 'output-to-input' && result.calculatedInputAmount && setInputAmount) {
113
+ if (effectiveDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && result.calculatedInputAmount && setInputAmount) {
114
114
  console.log('[EgressEstimates] Step 7: Handling reverse calculation - updating input amount', {
115
115
  calculatedInputAmount: result.calculatedInputAmount,
116
116
  });
@@ -139,7 +139,7 @@ export function useEgressEstimates({ evmAddress, solAddress, tokenIn, inputAmoun
139
139
  const actionableUsd = depositUsd - serviceFeeUsd;
140
140
  // Update destination amounts (matches Svelte Form.svelte lines 217-229)
141
141
  // For reverse calculation, preserve user's manual changes
142
- if (effectiveDirection === 'output-to-input') {
142
+ if (effectiveDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT) {
143
143
  console.log('[EgressEstimates] Step 9: Reverse calculation - preserving user output amounts');
144
144
  // Don't overwrite user's manual output changes
145
145
  // The outputs are already set correctly
@@ -1,5 +1,5 @@
1
1
  import type { Estimate, RelayQuoteResponse, DeBridgeOrderResponse } from '@silentswap/sdk';
2
- import { type AssetInfo } from '@silentswap/sdk';
2
+ import { type AssetInfo, type CalculationDirection } from '@silentswap/sdk';
3
3
  export interface OrderEstimateResult {
4
4
  ingressGasAmount: bigint;
5
5
  ingressRate: number;
@@ -31,7 +31,7 @@ export interface UseOrderEstimatesOptions {
31
31
  * Returns retention rates that account for bridge fees and slippage
32
32
  */
33
33
  export declare function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpactPercent, }?: UseOrderEstimatesOptions): {
34
- estimateOrder: (usdcPrice: number, sourceAsset: AssetInfo, sourcePrice: number, sourceAmount: number | string, destinationAssets: AssetInfo[], destinationPrices: number[], splits: number[], calculationDirection?: "input-to-output" | "output-to-input", outputAmounts?: string[]) => Promise<OrderEstimateResult>;
34
+ estimateOrder: (usdcPrice: number, sourceAsset: AssetInfo, sourcePrice: number, sourceAmount: number | string, destinationAssets: AssetInfo[], destinationPrices: number[], splits: number[], calculationDirection?: CalculationDirection, outputAmounts?: string[]) => Promise<OrderEstimateResult>;
35
35
  isLoading: boolean;
36
36
  error: Error | null;
37
37
  };
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useRef, useState, useMemo } from 'react';
2
2
  import BigNumber from 'bignumber.js';
3
- import { parseEvmCaip19, parseSolanaCaip19, isEvmNativeToken, isSolanaNativeToken, isSolanaAsset, EVM_PHONY_ADDRESS, SB58_ADDR_SOL_PROGRAM_SYSTEM, } from '@silentswap/sdk';
3
+ import { parseEvmCaip19, parseSolanaCaip19, isEvmNativeToken, isSolanaNativeToken, isSolanaAsset, EVM_PHONY_ADDRESS, SB58_ADDR_SOL_PROGRAM_SYSTEM, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from '@silentswap/sdk';
4
4
  import { useQuote } from './useQuote.js';
5
5
  /**
6
6
  * Hook for fetching both ingress and egress estimates in parallel
@@ -14,6 +14,7 @@ import { useQuote } from './useQuote.js';
14
14
  */
15
15
  export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpactPercent, } = {}) {
16
16
  const [error, setError] = useState(null);
17
+ const [isLoading, setIsLoading] = useState(false);
17
18
  // Determine address for ingress quotes based on source chain
18
19
  // For ingress, we need the address that matches the source chain (not sourceAsset)
19
20
  // For egress, we always start from Avalanche (EVM), so we can use evmAddress as default
@@ -56,7 +57,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
56
57
  * Fetch both ingress and egress estimates in parallel
57
58
  * Matches estimate_order() from Svelte app
58
59
  */
59
- const estimateOrder = useCallback(async (usdcPrice, sourceAsset, sourcePrice, sourceAmount, destinationAssets, destinationPrices, splits, calculationDirection = 'input-to-output', outputAmounts) => {
60
+ const estimateOrder = useCallback(async (usdcPrice, sourceAsset, sourcePrice, sourceAmount, destinationAssets, destinationPrices, splits, calculationDirection = CALCULATION_DIRECTION_INPUT_TO_OUTPUT, outputAmounts) => {
60
61
  // Validate inputs
61
62
  if (!sourceAsset) {
62
63
  throw new Error('sourceAsset is required');
@@ -71,7 +72,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
71
72
  throw new Error('All destinationAssets must have a valid caip19 property');
72
73
  }
73
74
  // For reverse calculation, validate output amounts
74
- if (calculationDirection === 'output-to-input') {
75
+ if (calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT) {
75
76
  if (!outputAmounts || outputAmounts.length !== destinationAssets.length) {
76
77
  throw new Error('outputAmounts are required for reverse calculation');
77
78
  }
@@ -125,7 +126,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
125
126
  // For reverse calculation, calculate total output USD value first
126
127
  let totalOutputUsd = 0;
127
128
  let calculatedInputAmount = undefined;
128
- if (calculationDirection === 'output-to-input' && outputAmounts) {
129
+ if (calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && outputAmounts) {
129
130
  console.log('[OrderEstimates] Step 4: Reverse calculation - calculating total output USD');
130
131
  // Calculate total USD value of outputs
131
132
  totalOutputUsd = destinationAssets.reduce((sum, destAsset, idx) => {
@@ -152,7 +153,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
152
153
  // Ingress: source chain -> Avalanche (USDC)
153
154
  // For reverse calculation, use EXACT_OUTPUT with calculated deposit USD
154
155
  // For normal calculation, use EXACT_INPUT with source amount
155
- calculationDirection === 'output-to-input' && totalOutputUsd > 0
156
+ calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && totalOutputUsd > 0
156
157
  ? estimateLiveIngress('ingress', sourceAsset.caip19, sourceChainId, sourceTokenAddress, totalOutputUsd / sourcePrice, // Approximate input for quote (will be refined)
157
158
  sourcePrice, abortController.signal, undefined, // recipientAddress (not needed for ingress)
158
159
  true, // isReverseCalculation
@@ -184,7 +185,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
184
185
  // For Solana destinations, use Solana address; for EVM, use EVM address
185
186
  const recipientAddress = isDestSolana ? solAddress : evmAddress;
186
187
  // For reverse calculation, use output amount directly with EXACT_OUTPUT
187
- if (calculationDirection === 'output-to-input' && outputAmounts && outputAmounts[idx]) {
188
+ if (calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && outputAmounts && outputAmounts[idx]) {
188
189
  const outputAmount = parseFloat(outputAmounts[idx]);
189
190
  // Use EXACT_OUTPUT for egress: we know the output amount, calculate required USDC
190
191
  // Pass the output amount directly (in human-readable format)
@@ -253,7 +254,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
253
254
  const egressRetentions = [];
254
255
  for (let idx = 0; idx < destinationAssets.length; idx++) {
255
256
  const egressResult = egressResults[idx];
256
- if (calculationDirection === 'output-to-input' && outputAmounts && outputAmounts[idx]) {
257
+ if (calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && outputAmounts && outputAmounts[idx]) {
257
258
  // For reverse calculation, use output USD value for interpolation
258
259
  const outputAmount = parseFloat(outputAmounts[idx]);
259
260
  const destPrice = destinationPrices[idx] || 1;
@@ -326,7 +327,7 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
326
327
  egressRetentions,
327
328
  });
328
329
  // For reverse calculation, extract calculated input amount from ingress result
329
- if (calculationDirection === 'output-to-input' && ingressResult.calculatedInputAmount) {
330
+ if (calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && ingressResult.calculatedInputAmount) {
330
331
  console.log('[OrderEstimates] Step 9: Reverse calculation - interpolating retention with calculated input', {
331
332
  calculatedInputAmount: ingressResult.calculatedInputAmount,
332
333
  });
@@ -380,19 +381,21 @@ export function useOrderEstimates({ evmAddress, solAddress, sourceAsset, maxImpa
380
381
  throw error;
381
382
  }
382
383
  })();
383
- // Store the in-flight request
384
+ // Store the in-flight request and update loading state
384
385
  inFlightRequestRef.current = requestPromise;
386
+ setIsLoading(true);
385
387
  // Clear in-flight request when promise completes (success or error)
386
388
  requestPromise.finally(() => {
387
389
  if (inFlightRequestRef.current === requestPromise) {
388
390
  inFlightRequestRef.current = null;
391
+ setIsLoading(false);
389
392
  }
390
393
  });
391
394
  return requestPromise;
392
395
  }, [estimateLiveIngress, estimateLiveEgress, interpolate, ingressAddress, egressAddress, sourceAsset, solAddress, evmAddress, maxImpactPercent]);
393
396
  return {
394
397
  estimateOrder,
395
- isLoading: !!inFlightRequestRef.current,
398
+ isLoading,
396
399
  error,
397
400
  };
398
401
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silentswap/react",
3
3
  "type": "module",
4
- "version": "0.0.49",
4
+ "version": "0.0.51",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@ensdomains/ensjs": "^4.2.0",
26
- "@silentswap/sdk": "0.0.49",
27
- "@silentswap/ui-kit": "0.0.49",
26
+ "@silentswap/sdk": "0.0.51",
27
+ "@silentswap/ui-kit": "0.0.51",
28
28
  "@solana/codecs-strings": "^5.1.0",
29
29
  "@solana/kit": "^5.1.0",
30
30
  "@solana/rpc": "^5.1.0",