@silentswap/react 0.0.73 → 0.0.75
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/SilentSwapContext.d.ts +3 -1
- package/dist/contexts/SilentSwapContext.js +4 -3
- package/dist/hooks/silent/useAuth.js +12 -0
- package/dist/hooks/silent/useBridgeExecution.js +14 -4
- package/dist/hooks/silent/useSilentQuote.d.ts +3 -2
- package/dist/hooks/silent/useSilentQuote.js +44 -1
- package/dist/hooks/silent/useWallet.js +10 -1
- package/package.json +3 -3
|
@@ -43,7 +43,7 @@ export interface SilentSwapContextType {
|
|
|
43
43
|
solanaRpcUrl?: string;
|
|
44
44
|
}
|
|
45
45
|
export declare function useSilentSwap(): SilentSwapContextType;
|
|
46
|
-
export declare function SilentSwapProvider({ children, client, evmAddress, solAddress, connector, isConnected, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment, baseUrl, solanaRpcUrl, walletClient, bitcoinAddress, bitcoinRpcUrl, proId, }: {
|
|
46
|
+
export declare function SilentSwapProvider({ children, client, evmAddress, solAddress, connector, isConnected, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment, baseUrl, solanaRpcUrl, walletClient, bitcoinAddress, bitcoinRpcUrl, proId, requestWalletConnect, }: {
|
|
47
47
|
children: React.ReactNode;
|
|
48
48
|
client: SilentSwapClient;
|
|
49
49
|
evmAddress?: string;
|
|
@@ -62,4 +62,6 @@ export declare function SilentSwapProvider({ children, client, evmAddress, solAd
|
|
|
62
62
|
bitcoinRpcUrl?: string;
|
|
63
63
|
/** Pro user ID for volume tracking (from ?pro= URL or localStorage silentswap:pro) */
|
|
64
64
|
proId?: string;
|
|
65
|
+
/** Optional: request wallet connection when walletClient is missing (e.g. user switched account on mobile). */
|
|
66
|
+
requestWalletConnect?: () => Promise<void>;
|
|
65
67
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -63,7 +63,7 @@ export function useSilentSwap() {
|
|
|
63
63
|
}
|
|
64
64
|
return context;
|
|
65
65
|
}
|
|
66
|
-
function SilentSwapInnerProvider({ children, client, evmAddress, solAddress, bitcoinAddress, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment, config, solanaRpcUrl, connector, isConnected = false, walletClient, proId, }) {
|
|
66
|
+
function SilentSwapInnerProvider({ children, client, evmAddress, solAddress, bitcoinAddress, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment, config, solanaRpcUrl, connector, isConnected = false, walletClient, proId, requestWalletConnect, }) {
|
|
67
67
|
// Authentication hook - only for EVM
|
|
68
68
|
const { auth, isLoading: authLoading } = useAuth({
|
|
69
69
|
client,
|
|
@@ -125,6 +125,7 @@ function SilentSwapInnerProvider({ children, client, evmAddress, solAddress, bit
|
|
|
125
125
|
generateWallet,
|
|
126
126
|
walletClient,
|
|
127
127
|
connector,
|
|
128
|
+
requestWalletConnect,
|
|
128
129
|
solanaConnector,
|
|
129
130
|
solanaConnection,
|
|
130
131
|
bitcoinConnector,
|
|
@@ -222,7 +223,7 @@ function SilentSwapInnerProvider({ children, client, evmAddress, solAddress, bit
|
|
|
222
223
|
solanaRpcUrl,
|
|
223
224
|
}, children: children });
|
|
224
225
|
}
|
|
225
|
-
export function SilentSwapProvider({ children, client, evmAddress, solAddress, connector, isConnected, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment = ENVIRONMENT.STAGING, baseUrl, solanaRpcUrl, walletClient, bitcoinAddress, bitcoinRpcUrl, proId, }) {
|
|
226
|
+
export function SilentSwapProvider({ children, client, evmAddress, solAddress, connector, isConnected, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment = ENVIRONMENT.STAGING, baseUrl, solanaRpcUrl, walletClient, bitcoinAddress, bitcoinRpcUrl, proId, requestWalletConnect, }) {
|
|
226
227
|
const config = useMemo(() => {
|
|
227
228
|
const computedBaseUrl = baseUrl ?? ENVIRONMENT_CONFIGS[environment].baseUrl;
|
|
228
229
|
console.log('[SilentSwapProvider] Creating config:', { environment, baseUrl, computedBaseUrl });
|
|
@@ -231,5 +232,5 @@ export function SilentSwapProvider({ children, client, evmAddress, solAddress, c
|
|
|
231
232
|
baseUrl: computedBaseUrl,
|
|
232
233
|
};
|
|
233
234
|
}, [environment, baseUrl]);
|
|
234
|
-
return (_jsx(AssetsProvider, { children: _jsx(PricesProvider, { children: _jsx(BalancesProvider, { evmAddress: evmAddress, solAddress: solAddress, solanaRpcUrl: solanaRpcUrl, bitcoinAddress: bitcoinAddress, bitcoinRpcUrl: bitcoinRpcUrl, children: _jsx(OrdersProvider, { baseUrl: config.baseUrl, children: _jsx(SilentSwapInnerProvider, { client: client, connector: connector, isConnected: isConnected, evmAddress: evmAddress, solAddress: solAddress, bitcoinAddress: bitcoinAddress, solanaConnector: solanaConnector, solanaConnection: solanaConnection, bitcoinConnector: bitcoinConnector, bitcoinConnection: bitcoinConnection, environment: environment, config: config, solanaRpcUrl: solanaRpcUrl, walletClient: walletClient, proId: proId, children: children }) }) }) }) }));
|
|
235
|
+
return (_jsx(AssetsProvider, { children: _jsx(PricesProvider, { children: _jsx(BalancesProvider, { evmAddress: evmAddress, solAddress: solAddress, solanaRpcUrl: solanaRpcUrl, bitcoinAddress: bitcoinAddress, bitcoinRpcUrl: bitcoinRpcUrl, children: _jsx(OrdersProvider, { baseUrl: config.baseUrl, children: _jsx(SilentSwapInnerProvider, { client: client, connector: connector, isConnected: isConnected, evmAddress: evmAddress, solAddress: solAddress, bitcoinAddress: bitcoinAddress, solanaConnector: solanaConnector, solanaConnection: solanaConnection, bitcoinConnector: bitcoinConnector, bitcoinConnection: bitcoinConnection, environment: environment, config: config, solanaRpcUrl: solanaRpcUrl, walletClient: walletClient, proId: proId, requestWalletConnect: requestWalletConnect, children: children }) }) }) }) }));
|
|
235
236
|
}
|
|
@@ -206,6 +206,18 @@ export function useAuth({ client, address, walletClient, domain = typeof window
|
|
|
206
206
|
const isAuthenticated = useCallback(() => {
|
|
207
207
|
return auth !== null && auth.authExpires > Date.now();
|
|
208
208
|
}, [auth]);
|
|
209
|
+
// Clear auth when address changes (e.g. user switched from MetaMask to Phantom)
|
|
210
|
+
const prevAddressRef = useRef(normalizedAddress);
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (prevAddressRef.current && normalizedAddress && prevAddressRef.current !== normalizedAddress) {
|
|
213
|
+
setAuth(null);
|
|
214
|
+
setNonce(null);
|
|
215
|
+
setError(null);
|
|
216
|
+
setIsAutoAuthenticating(false);
|
|
217
|
+
hasAutoAuthenticatedRef.current = false;
|
|
218
|
+
}
|
|
219
|
+
prevAddressRef.current = normalizedAddress;
|
|
220
|
+
}, [normalizedAddress]);
|
|
209
221
|
// Load cached auth on mount
|
|
210
222
|
useEffect(() => {
|
|
211
223
|
if (normalizedAddress && !auth && !isLoading) {
|
|
@@ -656,10 +656,20 @@ export function useBridgeExecution(walletClient, connector, solanaConnector, sol
|
|
|
656
656
|
// Note: allowanceTarget is not needed here because approval is already handled
|
|
657
657
|
// in executeSwap before bridge execution (matching Svelte silentswap.ts line 985-986).
|
|
658
658
|
// DeBridge will provide its own allowanceTarget from the response if needed.
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
659
|
+
try {
|
|
660
|
+
return await executeDebridgeBridge(sourceChainId, sourceTokenAddress, isSourceNative, bridgeUsdcAmount, depositCalldata, evmSignerAddress, // Use EVM signer address for deposit calldata
|
|
661
|
+
'', // allowanceTarget not needed - approval handled before bridge execution
|
|
662
|
+
depositorAddress, // Pass environment-based depositor address
|
|
663
|
+
walletClient, connector, setCurrentStep, onStatus);
|
|
664
|
+
}
|
|
665
|
+
catch (error) {
|
|
666
|
+
console.warn('DeBridge execution failed, falling back to relay.link bridge:', error instanceof Error ? error.message : String(error));
|
|
667
|
+
// On deBridge execution failure, fall back to relay.link using the same USDC amount.
|
|
668
|
+
// This matches the requirement: if deBridge quote/order fails, use relay quote/bridge.
|
|
669
|
+
return await executeRelayBridge(walletClient, connector, sourceChainId, sourceTokenAddress, isSourceNative, bridgeUsdcAmount, approveUsdcCalldata, depositCalldata, evmUserForBridge, // Use wallet account address for bridge quotes
|
|
670
|
+
depositorAddress, // Pass environment-based depositor address
|
|
671
|
+
setCurrentStep, onStatus);
|
|
672
|
+
}
|
|
663
673
|
}
|
|
664
674
|
else if (selectedProvider === 'relay') {
|
|
665
675
|
return await executeRelayBridge(walletClient, connector, sourceChainId, sourceTokenAddress, isSourceNative, bridgeUsdcAmount, approveUsdcCalldata, depositCalldata, evmUserForBridge, // Use wallet account address for bridge quotes
|
|
@@ -45,7 +45,8 @@ export interface useSilentQuoteOptions {
|
|
|
45
45
|
walletError?: Error | null;
|
|
46
46
|
/** Function to generate wallet (for retry on swap execution) */
|
|
47
47
|
generateWallet?: () => Promise<void>;
|
|
48
|
-
/**
|
|
48
|
+
/** Optional: request wallet connection when walletClient is missing (e.g. user switched account or declined). Called before throwing so UI can prompt user to connect and retry. */
|
|
49
|
+
requestWalletConnect?: () => Promise<void>;
|
|
49
50
|
/** Status update callback */
|
|
50
51
|
onStatus?: (status: string) => void;
|
|
51
52
|
/** Solana wallet connector (required for Solana swaps) */
|
|
@@ -98,4 +99,4 @@ export interface ExecuteSwapParams {
|
|
|
98
99
|
/** Optional integrator ID for tracking */
|
|
99
100
|
integratorId?: string;
|
|
100
101
|
}
|
|
101
|
-
export declare function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, wallet, walletLoading, walletError, generateWallet, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, getPrice, setDestinations, proId, }: useSilentQuoteOptions): useSilentQuoteReturn;
|
|
102
|
+
export declare function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, wallet, walletLoading, walletError, generateWallet, requestWalletConnect, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, getPrice, setDestinations, proId, }: useSilentQuoteOptions): useSilentQuoteReturn;
|
|
@@ -6,7 +6,7 @@ import { useOrderSigning } from './useOrderSigning.js';
|
|
|
6
6
|
import { useBridgeExecution } from './useBridgeExecution.js';
|
|
7
7
|
import { useTransaction } from '../useTransaction.js';
|
|
8
8
|
import { useQuoteCalculation } from './useQuoteCalculation.js';
|
|
9
|
-
export function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, wallet, walletLoading = false, walletError = null, generateWallet, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, getPrice, setDestinations, proId, }) {
|
|
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, }) {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
11
11
|
const [currentStep, setCurrentStep] = useState('');
|
|
12
12
|
const [quote, setQuote] = useState(null);
|
|
@@ -102,7 +102,29 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
102
102
|
if (!rawAddress) {
|
|
103
103
|
throw new Error('Address required for swap execution');
|
|
104
104
|
}
|
|
105
|
+
// If no wallet client (e.g. user switched accounts on mobile or declined), request connection then throw so user can retry
|
|
105
106
|
if (!walletClient) {
|
|
107
|
+
setCurrentStep('Wallet connection required...');
|
|
108
|
+
onStatus?.('Wallet connection required...');
|
|
109
|
+
const retryMessage = 'Please complete wallet connection in your wallet app and try again.';
|
|
110
|
+
try {
|
|
111
|
+
if (requestWalletConnect) {
|
|
112
|
+
await requestWalletConnect();
|
|
113
|
+
throw new Error(retryMessage);
|
|
114
|
+
}
|
|
115
|
+
// Fallback: try connector.connect() if available (e.g. wagmi connector)
|
|
116
|
+
const connectorWithConnect = connector;
|
|
117
|
+
if (connectorWithConnect?.connect) {
|
|
118
|
+
await connectorWithConnect.connect();
|
|
119
|
+
throw new Error(retryMessage);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
if (err instanceof Error && err.message === retryMessage) {
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
throw new Error('Wallet connection required for swap. Please connect your wallet and try again.');
|
|
127
|
+
}
|
|
106
128
|
throw new Error('Wallet client required for swap execution');
|
|
107
129
|
}
|
|
108
130
|
// Check if wallet generation previously failed - retry if so
|
|
@@ -145,6 +167,25 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
145
167
|
throw new Error('Wallet is being generated. Please wait for wallet generation to complete before executing swap.');
|
|
146
168
|
}
|
|
147
169
|
}
|
|
170
|
+
// Wallet generation hasn't started yet (e.g. auto-trigger effect hasn't fired) - trigger it now
|
|
171
|
+
if (!walletRef.current && !walletLoadingRef.current && !walletErrorRef.current && generateWalletRef.current) {
|
|
172
|
+
setCurrentStep('Generating wallet...');
|
|
173
|
+
onStatus?.('Generating wallet...');
|
|
174
|
+
try {
|
|
175
|
+
await generateWalletRef.current();
|
|
176
|
+
// Wait for wallet ref to update after generation
|
|
177
|
+
const maxWaitTime = 30000;
|
|
178
|
+
const checkInterval = 100;
|
|
179
|
+
const startTime = Date.now();
|
|
180
|
+
while (!walletRef.current && Date.now() - startTime < maxWaitTime) {
|
|
181
|
+
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
const error = err instanceof Error ? err : new Error('Failed to generate wallet');
|
|
186
|
+
throw new Error(`Wallet generation failed: ${error.message}. Please try again or ensure wallet is connected and authenticated.`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
148
189
|
// Final check: wallet must exist for swap execution
|
|
149
190
|
if (!walletRef.current) {
|
|
150
191
|
throw new Error('Wallet is required for swap execution. Please ensure wallet is connected and authenticated.');
|
|
@@ -287,6 +328,8 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
287
328
|
rawAddress,
|
|
288
329
|
evmAddress,
|
|
289
330
|
walletClient,
|
|
331
|
+
connector,
|
|
332
|
+
requestWalletConnect,
|
|
290
333
|
walletLoading,
|
|
291
334
|
walletError,
|
|
292
335
|
generateWallet,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useState, useEffect } from 'react';
|
|
1
|
+
import { useCallback, useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { createHdFacilitatorGroupFromEntropy, createEip712DocForWalletGeneration, queryDepositCount, loadWalletData, saveWalletData, clearWalletData, XT_TTL_SESSION_CACHE, ensureChain, base93ToBytes, bytesToBase93, } from '@silentswap/sdk';
|
|
3
3
|
import { getAddress, hexToBytes } from 'viem';
|
|
4
4
|
/**
|
|
@@ -182,6 +182,15 @@ export function useWallet({ client, address, auth, walletClient, connector, allD
|
|
|
182
182
|
clearWallet();
|
|
183
183
|
await generateWallet();
|
|
184
184
|
}, [clearWallet, generateWallet]);
|
|
185
|
+
// Clear wallet when address changes (e.g. user switched from MetaMask to Phantom)
|
|
186
|
+
const prevAddressRef = useRef(normalizedAddress);
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
if (prevAddressRef.current && normalizedAddress && prevAddressRef.current !== normalizedAddress) {
|
|
189
|
+
setWallet(null);
|
|
190
|
+
setError(null);
|
|
191
|
+
}
|
|
192
|
+
prevAddressRef.current = normalizedAddress;
|
|
193
|
+
}, [normalizedAddress]);
|
|
185
194
|
// Auto-load cached wallet on mount
|
|
186
195
|
useEffect(() => {
|
|
187
196
|
if (normalizedAddress && !wallet && !isLoading) {
|
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.75",
|
|
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.75",
|
|
28
|
+
"@silentswap/ui-kit": "0.0.75",
|
|
29
29
|
"@solana/codecs-strings": "^5.1.0",
|
|
30
30
|
"@solana/kit": "^5.1.0",
|
|
31
31
|
"@solana/rpc": "^5.1.0",
|