@silentswap/react 0.0.82 → 0.0.83
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/contexts/SwapFormEstimatesContext.d.ts +3 -1
- package/dist/contexts/SwapFormEstimatesContext.js +6 -5
- package/dist/hooks/silent/useBridgeExecution.d.ts +2 -0
- package/dist/hooks/silent/useBridgeExecution.js +10 -0
- package/dist/hooks/silent/useSilentQuote.js +4 -1
- package/dist/hooks/usePlatformHealth.d.ts +1 -1
- package/dist/hooks/usePlatformHealth.js +3 -3
- package/dist/hooks/useQuote.d.ts +3 -1
- package/dist/hooks/useQuote.js +7 -4
- package/package.json +3 -3
|
@@ -11,6 +11,8 @@ export interface SwapFormEstimatesProviderProps {
|
|
|
11
11
|
children: React.ReactNode;
|
|
12
12
|
tokenIn: AssetInfo | null;
|
|
13
13
|
fetchEstimates: (direction?: CalculationDirection) => Promise<void>;
|
|
14
|
+
/** Override service fee rate. Pass 0 for simple swaps (no service fee). */
|
|
15
|
+
serviceFeeRate?: number;
|
|
14
16
|
}
|
|
15
|
-
export declare function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, }: SwapFormEstimatesProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, serviceFeeRate: serviceFeeRateOverride, }: SwapFormEstimatesProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
16
18
|
export declare function useSwapFormEstimatesContext(): SwapFormEstimatesContextType;
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import React, { createContext, useContext, useCallback, useRef, useMemo, useEffect } from 'react';
|
|
4
4
|
import { useSwap, X_RANGE_SLIDER_MIN_GAP } from '../hooks/useSwap.js';
|
|
5
|
-
import { usePricesContext } from './PricesContext.js';
|
|
6
5
|
import { usePlatformHealthContext } from '../hooks/usePlatformHealth.js';
|
|
6
|
+
import { usePricesContext } from './PricesContext.js';
|
|
7
7
|
import { getAssetByCaip19, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from '@silentswap/sdk';
|
|
8
8
|
const XT_DELAY_DEBOUNCE_QUOTE = 550;
|
|
9
9
|
const SwapFormEstimatesContext = createContext(undefined);
|
|
10
|
-
export function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, }) {
|
|
10
|
+
export function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, serviceFeeRate: serviceFeeRateOverride, }) {
|
|
11
11
|
const setSplits = useSwap((state) => state.setSplits);
|
|
12
12
|
const setInputAmount = useSwap((state) => state.setInputAmount);
|
|
13
13
|
const inputAmount = useSwap((state) => state.inputAmount);
|
|
@@ -16,7 +16,8 @@ export function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, }
|
|
|
16
16
|
const isDraggingSlider = useSwap((state) => state.isDraggingSlider);
|
|
17
17
|
const updateDestinationAmount = useSwap((state) => state.updateDestinationAmount);
|
|
18
18
|
const { getPrice } = usePricesContext();
|
|
19
|
-
const { getServiceFeeRate } = usePlatformHealthContext();
|
|
19
|
+
const { getServiceFeeRate: getPlatformServiceFeeRate } = usePlatformHealthContext();
|
|
20
|
+
const getServiceFeeRate = useCallback(() => (serviceFeeRateOverride !== undefined ? serviceFeeRateOverride : getPlatformServiceFeeRate()), [serviceFeeRateOverride, getPlatformServiceFeeRate]);
|
|
20
21
|
const fetchEstimatesRef = useRef(fetchEstimates);
|
|
21
22
|
const debounceTimerRef = useRef(null);
|
|
22
23
|
const isRecalculatingInputRef = useRef(false);
|
|
@@ -133,7 +134,7 @@ export function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, }
|
|
|
133
134
|
if (tokenInPrice != null && tokenInPrice > 0) {
|
|
134
135
|
// Calculate required input USD accounting for service fee
|
|
135
136
|
// Formula: inputUsd = outputUsd / (1 - serviceFeeRate)
|
|
136
|
-
const serviceFeeRate = getServiceFeeRate()
|
|
137
|
+
const serviceFeeRate = getServiceFeeRate();
|
|
137
138
|
const requiredInputUsd = totalUsd / (1 - serviceFeeRate);
|
|
138
139
|
const currentInputUsd = currentInputAmountNum * tokenInPrice;
|
|
139
140
|
const USD_TOLERANCE = 0.01;
|
|
@@ -276,7 +277,7 @@ export function SwapFormEstimatesProvider({ children, tokenIn, fetchEstimates, }
|
|
|
276
277
|
// Apply service fee to get actionable USD (amount available for outputs after fee deduction)
|
|
277
278
|
// Formula: serviceFeeUsd = depositUsd * serviceFeeRate
|
|
278
279
|
// actionableUsd = depositUsd - serviceFeeUsd
|
|
279
|
-
const serviceFeeRate = getServiceFeeRate()
|
|
280
|
+
const serviceFeeRate = getServiceFeeRate();
|
|
280
281
|
const serviceFeeUsd = totalUsdValue * serviceFeeRate;
|
|
281
282
|
const actionableUsd = totalUsdValue - serviceFeeUsd;
|
|
282
283
|
// Normalize splits for single destination - ensure it's always [1.0]
|
|
@@ -3,6 +3,8 @@ import type { Connector } from 'wagmi';
|
|
|
3
3
|
import type { DepositParams } from '@silentswap/sdk';
|
|
4
4
|
import type { SolanaWalletConnector, SolanaConnection } from './solana-transaction.js';
|
|
5
5
|
import type { BitcoinWalletConnector, BitcoinConnection } from './bitcoin-transaction.js';
|
|
6
|
+
/** Delay after approve tx so RPC/nodes confirm before next tx (avoids MetaMask RPC errors) */
|
|
7
|
+
export declare const APPROVE_POST_DELAY_MS = 7000;
|
|
6
8
|
/**
|
|
7
9
|
* Result from executing a bridge transaction
|
|
8
10
|
*/
|
|
@@ -5,6 +5,8 @@ import { createSolanaTransactionExecutor, convertRelaySolanaStepToTransaction }
|
|
|
5
5
|
import { createBitcoinTransactionExecutor, convertRelayBitcoinStepToTransaction } from './bitcoin-transaction.js';
|
|
6
6
|
const S0X_ADDR_EVM_ZERO = '0x0000000000000000000000000000000000000000';
|
|
7
7
|
const XG_UINT256_MAX = (1n << 256n) - 1n;
|
|
8
|
+
/** Delay after approve tx so RPC/nodes confirm before next tx (avoids MetaMask RPC errors) */
|
|
9
|
+
export const APPROVE_POST_DELAY_MS = 7000;
|
|
8
10
|
/**
|
|
9
11
|
* Get normalized wallet account address from wallet client
|
|
10
12
|
* This ensures the address matches the account that will send transactions
|
|
@@ -802,6 +804,11 @@ setCurrentStep, onStatus) {
|
|
|
802
804
|
status: receipt.status,
|
|
803
805
|
});
|
|
804
806
|
}
|
|
807
|
+
if (step.id === 'approve') {
|
|
808
|
+
setCurrentStep('Waiting for network...');
|
|
809
|
+
onStatus?.('Waiting for network...');
|
|
810
|
+
await new Promise((resolve) => setTimeout(resolve, APPROVE_POST_DELAY_MS));
|
|
811
|
+
}
|
|
805
812
|
}
|
|
806
813
|
}
|
|
807
814
|
// Find request ID for status monitoring
|
|
@@ -896,6 +903,9 @@ walletClient, connector, setCurrentStep, onStatus) {
|
|
|
896
903
|
chain: null,
|
|
897
904
|
});
|
|
898
905
|
await waitForTransactionConfirmation(hash, publicClient);
|
|
906
|
+
setCurrentStep('Waiting for network...');
|
|
907
|
+
onStatus?.('Waiting for network...');
|
|
908
|
+
await new Promise((resolve) => setTimeout(resolve, APPROVE_POST_DELAY_MS));
|
|
899
909
|
}
|
|
900
910
|
retryCount++;
|
|
901
911
|
continue;
|
|
@@ -3,7 +3,7 @@ import { hexToBase58, isSolanaAsset, isBitcoinAsset, parseEvmCaip19, S_CAIP19_US
|
|
|
3
3
|
import { getAddress } from 'viem';
|
|
4
4
|
import { useQuoteFetching } from './useQuoteFetching.js';
|
|
5
5
|
import { useOrderSigning } from './useOrderSigning.js';
|
|
6
|
-
import { useBridgeExecution } from './useBridgeExecution.js';
|
|
6
|
+
import { APPROVE_POST_DELAY_MS, useBridgeExecution } from './useBridgeExecution.js';
|
|
7
7
|
import { useTransaction } from '../useTransaction.js';
|
|
8
8
|
import { useQuoteCalculation } from './useQuoteCalculation.js';
|
|
9
9
|
export function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, wallet, walletLoading = false, walletError = null, generateWallet, requestWalletConnect, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, getPrice, setDestinations, proId, }) {
|
|
@@ -281,6 +281,9 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
281
281
|
const sourceChainId = parseInt(sourceAssetMatch[1]);
|
|
282
282
|
const tokenAddress = sourceAssetMatch[2];
|
|
283
283
|
await approveTokenSpending(sourceChainId, tokenAddress, effectiveAllowanceTarget, sourceAmountInUnits, evmSignerAddress);
|
|
284
|
+
// Delay after approve so RPC/nodes confirm approval before next tx (avoids MetaMask RPC errors)
|
|
285
|
+
setCurrentStep('Waiting for network...');
|
|
286
|
+
await new Promise((resolve) => setTimeout(resolve, APPROVE_POST_DELAY_MS));
|
|
284
287
|
}
|
|
285
288
|
}
|
|
286
289
|
// Handle EVM bridge swaps
|
|
@@ -23,7 +23,7 @@ export type PlatformHealthContextType = {
|
|
|
23
23
|
};
|
|
24
24
|
getMinimumDepositUsd: () => number | null;
|
|
25
25
|
getMaximumDepositUsd: () => number | null;
|
|
26
|
-
getServiceFeeRate: () => number
|
|
26
|
+
getServiceFeeRate: () => number;
|
|
27
27
|
};
|
|
28
28
|
export type PlatformHealthProviderProps = {
|
|
29
29
|
children: React.ReactNode;
|
|
@@ -89,12 +89,12 @@ export function PlatformHealthProvider({ children, proId, onFormDisabledChange,
|
|
|
89
89
|
}, [maximumDepositUusdc]);
|
|
90
90
|
const getServiceFeeRate = useCallback(() => {
|
|
91
91
|
if (!serviceFeeRate)
|
|
92
|
-
return
|
|
92
|
+
return 0.01;
|
|
93
93
|
try {
|
|
94
|
-
return +serviceFeeRate;
|
|
94
|
+
return +serviceFeeRate || 0.01;
|
|
95
95
|
}
|
|
96
96
|
catch {
|
|
97
|
-
return
|
|
97
|
+
return 0.01;
|
|
98
98
|
}
|
|
99
99
|
}, [serviceFeeRate]);
|
|
100
100
|
// Validate deposit amount against min/max limits
|
package/dist/hooks/useQuote.d.ts
CHANGED
|
@@ -41,9 +41,11 @@ export interface useQuoteReturn {
|
|
|
41
41
|
* @param dstToken - Destination token address (0x0 for native)
|
|
42
42
|
* @param recipientAddress - Optional recipient address (required for Solana destinations)
|
|
43
43
|
* @param sourceAddress - Optional source chain address (for relay.link, must match source chain format)
|
|
44
|
+
* @param tradeType - 'EXACT_INPUT' (default) or 'EXACT_OUTPUT'
|
|
45
|
+
* @param dstAmount - Destination amount in token units (required for EXACT_OUTPUT)
|
|
44
46
|
* @returns Promise resolving to best quote with all details
|
|
45
47
|
*/
|
|
46
|
-
getQuote: (srcChainId: number, srcToken: string, srcAmount: string, dstChainId: number, dstToken: string, recipientAddress?: string, sourceAddress?: string) => Promise<BridgeQuoteResult>;
|
|
48
|
+
getQuote: (srcChainId: number, srcToken: string, srcAmount: string, dstChainId: number, dstToken: string, recipientAddress?: string, sourceAddress?: string, tradeType?: 'EXACT_INPUT' | 'EXACT_OUTPUT', dstAmount?: string) => Promise<BridgeQuoteResult>;
|
|
47
49
|
/**
|
|
48
50
|
* Get live estimate for a given direction
|
|
49
51
|
* @param direction - 'ingress' (into Silent) or 'egress' (out of Silent)
|
package/dist/hooks/useQuote.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import BigNumber from 'bignumber.js';
|
|
3
|
-
import { NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE, X_MAX_IMPACT_PERCENT, getBridgeQuote
|
|
3
|
+
import { NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE, X_MAX_IMPACT_PERCENT, getBridgeQuote, interpolateSamples as sdkInterpolateSamples, fetchRelayQuote, fetchDebridgeOrder, normalizeAddress, getAssetByCaip19, N_DEBRIDGE_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_SOLANA, SB58_ADDR_SOL_PROGRAM_SYSTEM, S0X_ADDR_EVM_RELAY_LINK_DEAD, SB58_ADDR_SOL_RELAY_LINK_RECIPIENT, isSolanaAsset, isBitcoinAsset, EVM_PHONY_ADDRESS, } from '@silentswap/sdk';
|
|
4
4
|
// Constants for estimateLive
|
|
5
5
|
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
6
6
|
/**
|
|
@@ -43,7 +43,7 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
43
43
|
/**
|
|
44
44
|
* Get quote for cross-chain swap
|
|
45
45
|
*/
|
|
46
|
-
const getQuote = useCallback(async (srcChainId, srcToken, srcAmount, dstChainId, dstToken, recipientAddress, sourceAddress) => {
|
|
46
|
+
const getQuote = useCallback(async (srcChainId, srcToken, srcAmount, dstChainId, dstToken, recipientAddress, sourceAddress, tradeType = 'EXACT_INPUT', dstAmount) => {
|
|
47
47
|
console.log('[Quote] Step 1: Starting getQuote', {
|
|
48
48
|
srcChainId,
|
|
49
49
|
srcToken,
|
|
@@ -52,6 +52,8 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
52
52
|
dstToken,
|
|
53
53
|
hasRecipientAddress: !!recipientAddress,
|
|
54
54
|
hasSourceAddress: !!sourceAddress,
|
|
55
|
+
tradeType,
|
|
56
|
+
dstAmount,
|
|
55
57
|
});
|
|
56
58
|
if (!normalizedAddress) {
|
|
57
59
|
throw new Error('Address required for bridge quote operations');
|
|
@@ -70,9 +72,10 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
70
72
|
// normalizedAddress can be EVM (0x...) or Solana (base58) address
|
|
71
73
|
// sourceAddress is the address format for the source chain (for relay.link)
|
|
72
74
|
console.log('[Quote] Step 3: Calling sdkGetBridgeQuote');
|
|
73
|
-
const result = await
|
|
75
|
+
const result = await getBridgeQuote(srcChainId, srcTokenNorm, srcAmount, dstChainId, dstTokenNorm, normalizedAddress, signal, recipientAddress, // Pass recipient address for Solana destinations
|
|
74
76
|
sourceAddress, // Pass source address for relay.link (must match source chain format)
|
|
75
|
-
forceProvider
|
|
77
|
+
forceProvider, // Optional: use only this provider for testing
|
|
78
|
+
tradeType, dstAmount);
|
|
76
79
|
console.log('[Quote] Step 4: getQuote completed successfully', {
|
|
77
80
|
provider: result.provider,
|
|
78
81
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silentswap/react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.83",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@bigmi/core": "^0.6.5",
|
|
26
26
|
"@ensdomains/ensjs": "^4.2.0",
|
|
27
|
-
"@silentswap/sdk": "0.0.
|
|
28
|
-
"@silentswap/ui-kit": "0.0.
|
|
27
|
+
"@silentswap/sdk": "0.0.83",
|
|
28
|
+
"@silentswap/ui-kit": "0.0.83",
|
|
29
29
|
"@solana/codecs-strings": "^5.1.0",
|
|
30
30
|
"@solana/kit": "^5.1.0",
|
|
31
31
|
"@solana/rpc": "^5.1.0",
|