@silentswap/react 0.0.43 → 0.0.45

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.
@@ -45,6 +45,7 @@ export const OrdersProvider = ({ children }) => {
45
45
  // Get baseUrl from environment
46
46
  const { config } = useSilentSwap();
47
47
  const baseUrl = config.baseUrl;
48
+ console.log('[OrdersContext] Using baseUrl:', baseUrl, 'from config:', config);
48
49
  // Fetch recent orders from API (matches Svelte implementation)
49
50
  const request_recent_orders = useCallback(async (sb58_auth_view) => {
50
51
  try {
@@ -197,9 +197,13 @@ function SilentSwapInnerProvider({ children, client, evmAddress, solAddress, sol
197
197
  }, children: children });
198
198
  }
199
199
  export function SilentSwapProvider({ children, client, evmAddress, solAddress, connector, isConnected, solanaConnector, solanaConnection, environment = ENVIRONMENT.STAGING, baseUrl, solanaRpcUrl, walletClient, }) {
200
- const config = useMemo(() => ({
201
- environment,
202
- baseUrl: baseUrl ?? ENVIRONMENT_CONFIGS[environment].baseUrl,
203
- }), [environment, baseUrl]);
204
- return (_jsx(AssetsProvider, { children: _jsx(PricesProvider, { children: _jsx(BalancesProvider, { evmAddress: evmAddress, solAddress: solAddress, solanaRpcUrl: solanaRpcUrl, children: _jsx(OrdersProvider, { children: _jsx(SilentSwapInnerProvider, { client: client, connector: connector, isConnected: isConnected, evmAddress: evmAddress, solAddress: solAddress, solanaConnector: solanaConnector, solanaConnection: solanaConnection, environment: environment, config: config, solanaRpcUrl: solanaRpcUrl, walletClient: walletClient, children: children }) }) }) }) }));
200
+ const config = useMemo(() => {
201
+ const computedBaseUrl = baseUrl ?? ENVIRONMENT_CONFIGS[environment].baseUrl;
202
+ console.log('[SilentSwapProvider] Creating config:', { environment, baseUrl, computedBaseUrl });
203
+ return {
204
+ environment,
205
+ baseUrl: computedBaseUrl,
206
+ };
207
+ }, [environment, baseUrl]);
208
+ return (_jsx(AssetsProvider, { children: _jsx(PricesProvider, { children: _jsx(BalancesProvider, { evmAddress: evmAddress, solAddress: solAddress, solanaRpcUrl: solanaRpcUrl, children: _jsx(SilentSwapInnerProvider, { client: client, connector: connector, isConnected: isConnected, evmAddress: evmAddress, solAddress: solAddress, solanaConnector: solanaConnector, solanaConnection: solanaConnection, environment: environment, config: config, solanaRpcUrl: solanaRpcUrl, walletClient: walletClient, children: _jsx(OrdersProvider, { children: children }) }) }) }) }));
205
209
  }
@@ -0,0 +1,42 @@
1
+ import type { BridgeTransaction } from '@silentswap/sdk';
2
+ /**
3
+ * Bitcoin wallet connector interface
4
+ * Compatible with Bitcoin wallet adapters (e.g., Unisat, Xverse, etc.)
5
+ */
6
+ export interface BitcoinWalletConnector {
7
+ signPsbt: (psbt: string) => Promise<string>;
8
+ sendPsbt: (psbt: string) => Promise<string>;
9
+ getAccounts: () => Promise<string[]>;
10
+ currentAccount?: string | null;
11
+ }
12
+ /**
13
+ * Bitcoin connection interface
14
+ * For Bitcoin, we typically don't need a separate connection object
15
+ * as wallets handle RPC communication internally
16
+ */
17
+ export interface BitcoinConnection {
18
+ }
19
+ /**
20
+ * Bitcoin transaction executor type
21
+ * Similar to SolanaTransactionExecutor but for Bitcoin PSBTs
22
+ */
23
+ export type BitcoinTransactionExecutor = (tx: BridgeTransaction) => Promise<string>;
24
+ /**
25
+ * Create a Bitcoin transaction executor
26
+ * This function creates a transaction executor that can handle Bitcoin transactions
27
+ * from relay.link bridge quotes
28
+ *
29
+ * @param connector - Bitcoin wallet connector
30
+ * @param connection - Bitcoin connection (optional, for consistency with Solana pattern)
31
+ * @returns Bitcoin transaction executor function
32
+ */
33
+ export declare function createBitcoinTransactionExecutor(connector: BitcoinWalletConnector, _connection?: BitcoinConnection): BitcoinTransactionExecutor;
34
+ /**
35
+ * Helper to convert relay.link Bitcoin step data to BridgeTransaction
36
+ * Note: Bitcoin transactions from relay.link provide PSBTs in base64 format in the 'psbt' field
37
+ */
38
+ export declare function convertRelayBitcoinStepToTransaction(stepData: {
39
+ psbt?: string;
40
+ hex?: string;
41
+ data?: string;
42
+ }, chainId: number): BridgeTransaction;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Create a Bitcoin transaction executor
3
+ * This function creates a transaction executor that can handle Bitcoin transactions
4
+ * from relay.link bridge quotes
5
+ *
6
+ * @param connector - Bitcoin wallet connector
7
+ * @param connection - Bitcoin connection (optional, for consistency with Solana pattern)
8
+ * @returns Bitcoin transaction executor function
9
+ */
10
+ export function createBitcoinTransactionExecutor(connector, _connection) {
11
+ return async (tx) => {
12
+ try {
13
+ if (!connector.currentAccount) {
14
+ const accounts = await connector.getAccounts();
15
+ if (!accounts || accounts.length === 0) {
16
+ throw new Error('Bitcoin wallet not connected');
17
+ }
18
+ }
19
+ console.log('Creating Bitcoin transaction:', {
20
+ hasData: !!tx.data,
21
+ hasInstructions: !!tx.instructions,
22
+ instructionsCount: tx.instructions?.length,
23
+ });
24
+ // Bitcoin transactions from relay.link come as PSBTs (Partially Signed Bitcoin Transactions)
25
+ // The PSBT is provided in base64 format in the 'psbt' field of the step data
26
+ // We store it in tx.data, but it's actually base64, not hex
27
+ // Check if we have a psbt field in the transaction (for direct PSBT passing)
28
+ let psbtBase64;
29
+ // Check if tx has a psbt property (for direct PSBT passing)
30
+ if (tx.psbt) {
31
+ psbtBase64 = tx.psbt;
32
+ }
33
+ else if (tx.data) {
34
+ // If data is provided, check if it's base64 or hex
35
+ const dataStr = tx.data.replace(/^0x/, '');
36
+ // Check if it looks like base64 (contains base64 characters and is longer)
37
+ // Base64 PSBTs from relay.link are typically long strings without 0x prefix
38
+ // Hex would be even length and only contain 0-9a-f
39
+ const isBase64 = /^[A-Za-z0-9+/=]+$/.test(dataStr) && dataStr.length > 100;
40
+ if (isBase64) {
41
+ // Already base64
42
+ psbtBase64 = dataStr;
43
+ }
44
+ else {
45
+ // Convert hex to base64
46
+ const psbtBytes = Buffer.from(dataStr, 'hex');
47
+ psbtBase64 = psbtBytes.toString('base64');
48
+ }
49
+ }
50
+ else {
51
+ throw new Error('Bitcoin transaction must have PSBT data');
52
+ }
53
+ console.log('Requesting PSBT signature...');
54
+ // Sign PSBT with wallet (wallet expects base64)
55
+ const signedPsbt = await connector.signPsbt(psbtBase64);
56
+ console.log('PSBT signed');
57
+ console.log('Sending PSBT...');
58
+ // Send signed PSBT (wallet returns base64)
59
+ const txHash = await connector.sendPsbt(signedPsbt);
60
+ console.log('Bitcoin transaction sent:', txHash);
61
+ return txHash;
62
+ }
63
+ catch (error) {
64
+ console.error('Bitcoin transaction execution failed:', {
65
+ error: error instanceof Error ? error.message : String(error),
66
+ stack: error instanceof Error ? error.stack : undefined,
67
+ });
68
+ throw error;
69
+ }
70
+ };
71
+ }
72
+ /**
73
+ * Helper to convert relay.link Bitcoin step data to BridgeTransaction
74
+ * Note: Bitcoin transactions from relay.link provide PSBTs in base64 format in the 'psbt' field
75
+ */
76
+ export function convertRelayBitcoinStepToTransaction(stepData, chainId) {
77
+ // Extract PSBT from step data
78
+ // relay.link provides it as 'psbt' in base64 format (see example response)
79
+ const psbtData = stepData.psbt || stepData.hex || stepData.data;
80
+ if (!psbtData) {
81
+ throw new Error('Bitcoin transaction step must have psbt, hex, or data field');
82
+ }
83
+ // relay.link provides PSBT in base64 format directly
84
+ // We store it in the transaction object with a psbt property for direct access
85
+ // Also store in data field for compatibility (as base64 string, not hex)
86
+ return {
87
+ chainId,
88
+ data: psbtData, // Store base64 PSBT (type assertion for compatibility)
89
+ // Add psbt property for direct access
90
+ ...{ psbt: psbtData },
91
+ };
92
+ }
@@ -1,6 +1,6 @@
1
1
  import { useCallback } from 'react';
2
- import { createPublicClient, http, encodeFunctionData, erc20Abi, getAddress } from 'viem';
3
- import { ensureChain, waitForTransactionConfirmation, NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, X_MAX_IMPACT_PERCENT, getRelayStatus, getDebridgeStatus, fetchDebridgeOrder, fetchRelayQuote, createPhonyDepositCalldata, isSolanaAsset, parseSolanaCaip19, isSolanaNativeToken, isSplToken, N_RELAY_CHAIN_ID_SOLANA, SB58_ADDR_SOL_PROGRAM_SYSTEM, getChainById, } from '@silentswap/sdk';
2
+ import { encodeFunctionData, erc20Abi, getAddress } from 'viem';
3
+ import { ensureChain, waitForTransactionConfirmation, createPublicClientWithRpc, NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, X_MAX_IMPACT_PERCENT, getRelayStatus, getDebridgeStatus, fetchDebridgeOrder, fetchRelayQuote, createPhonyDepositCalldata, isSolanaAsset, parseSolanaCaip19, isSolanaNativeToken, isSplToken, N_RELAY_CHAIN_ID_SOLANA, SB58_ADDR_SOL_PROGRAM_SYSTEM, getChainById, } from '@silentswap/sdk';
4
4
  import { createSolanaTransactionExecutor, convertRelaySolanaStepToTransaction } from './solana-transaction.js';
5
5
  const S0X_ADDR_EVM_ZERO = '0x0000000000000000000000000000000000000000';
6
6
  const XG_UINT256_MAX = (1n << 256n) - 1n;
@@ -28,14 +28,8 @@ async function ensureChainAndCreateClient(chainId, walletClient, connector) {
28
28
  const wallet = await ensureChain(chainId, walletClient, connector);
29
29
  // Use wallet's chain if available, otherwise look up chain by ID
30
30
  const chain = wallet.chain || getChainById(chainId);
31
- if (!chain) {
32
- throw new Error(`Unsupported chain ID: ${chainId}. Please ensure the chain is supported.`);
33
- }
34
- // Create public client - viem has complex union types that TypeScript struggles with
35
- const publicClient = createPublicClient({
36
- chain,
37
- transport: http(),
38
- });
31
+ // Create public client with RPC fallback configuration
32
+ const publicClient = createPublicClientWithRpc(chainId, chain);
39
33
  return { wallet, publicClient };
40
34
  }
41
35
  /**
@@ -4,28 +4,50 @@ import { useSilentSwap } from '../contexts/SilentSwapContext.js';
4
4
  * Hook to fetch the current platform status, fee rates, and limits
5
5
  */
6
6
  export function useStatus() {
7
- const { config } = useSilentSwap();
7
+ const { config, client } = useSilentSwap();
8
8
  const baseUrl = config.baseUrl;
9
9
  const [status, setStatus] = useState({});
10
10
  const [isLoading, setIsLoading] = useState(true);
11
11
  const [error, setError] = useState(null);
12
12
  useEffect(() => {
13
+ // Skip if baseUrl is not yet available (shouldn't happen, but safety check)
14
+ if (!baseUrl) {
15
+ console.warn('[useStatus] baseUrl is not available yet');
16
+ return;
17
+ }
18
+ // Skip if we're using the default/placeholder context
19
+ // The DEFAULT_CONTEXT has client: {} as SilentSwapClient (empty object placeholder)
20
+ // Real SilentSwapClient instances are class instances, not plain objects
21
+ // Check if client is the placeholder by verifying it's a plain empty object
22
+ const isPlaceholderClient = client &&
23
+ typeof client === 'object' &&
24
+ Object.getPrototypeOf(client) === Object.prototype &&
25
+ Object.keys(client).length === 0;
26
+ if (isPlaceholderClient) {
27
+ console.warn('[useStatus] Context not yet initialized (placeholder client detected), skipping fetch until real context is available');
28
+ setIsLoading(false);
29
+ return;
30
+ }
13
31
  let isMounted = true;
14
32
  const fetchStatus = async () => {
15
33
  try {
16
34
  setIsLoading(true);
17
- const response = await fetch(`${baseUrl}/status`);
35
+ const statusUrl = `${baseUrl}/status`;
36
+ console.log('[useStatus] Fetching status from:', statusUrl, 'environment:', config.environment);
37
+ const response = await fetch(statusUrl);
18
38
  if (!response.ok) {
19
39
  throw new Error(`Failed to fetch status: ${response.statusText}`);
20
40
  }
21
41
  const data = await response.json();
22
42
  if (isMounted) {
43
+ console.log('[useStatus] Status fetched successfully from:', statusUrl);
23
44
  setStatus(data);
24
45
  setError(null);
25
46
  }
26
47
  }
27
48
  catch (err) {
28
49
  if (isMounted) {
50
+ console.error('[useStatus] Failed to fetch status from:', baseUrl, err);
29
51
  setError(err instanceof Error ? err : new Error('Failed to fetch status'));
30
52
  // Use defaults on error
31
53
  setStatus({});
@@ -41,7 +63,7 @@ export function useStatus() {
41
63
  return () => {
42
64
  isMounted = false;
43
65
  };
44
- }, [baseUrl]);
66
+ }, [baseUrl, config.environment]);
45
67
  // Convert overheadUsd from string to number
46
68
  const overheadUsd = status.overheadUsd ? parseFloat(status.overheadUsd) : 0;
47
69
  // serviceFeeRate is a Decimal (0.01 = 1%), convert to number
@@ -1,6 +1,6 @@
1
1
  import { type AssetInfo } from '@silentswap/sdk';
2
2
  export declare const X_RANGE_SLIDER_MIN_GAP = 0.01;
3
- export declare const OUTPUT_LIMIT = 5;
3
+ export declare const OUTPUT_LIMIT = 10;
4
4
  export declare const DEFAULT_SOURCE_ASSET = "eip155:1/slip44:60";
5
5
  export declare const DEFAULT_DEST_ASSET = "eip155:1/erc20:0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599";
6
6
  export declare const DEFAULT_OUTPUT_ASSET = "eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
@@ -4,7 +4,7 @@ import { getAssetByCaip19 } from '@silentswap/sdk';
4
4
  const DEFAULT_SLIPPAGE = 1;
5
5
  // Constants matching Svelte app
6
6
  export const X_RANGE_SLIDER_MIN_GAP = 0.01;
7
- export const OUTPUT_LIMIT = 5;
7
+ export const OUTPUT_LIMIT = 10;
8
8
  // Default assets
9
9
  export const DEFAULT_SOURCE_ASSET = 'eip155:1/slip44:60'; // ETH on Ethereum
10
10
  export const DEFAULT_DEST_ASSET = 'eip155:1/erc20:0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599'; // WBTC on Ethereum
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useState } from 'react';
2
- import { createPublicClient, http, erc20Abi } from 'viem';
3
- import { executeRelayBridge, executeDebridgeBridge, getBridgeStatus, createTransactionExecutor, createChainSwitcher, ensureChain, waitForTransactionConfirmation, parseTransactionRequestForViem, getChainById, } from '@silentswap/sdk';
2
+ import { erc20Abi } from 'viem';
3
+ import { executeRelayBridge, executeDebridgeBridge, getBridgeStatus, createTransactionExecutor, createChainSwitcher, ensureChain, waitForTransactionConfirmation, parseTransactionRequestForViem, createPublicClientWithRpc, getChainById, } from '@silentswap/sdk';
4
4
  import { createSolanaTransactionExecutor } from './silent/solana-transaction.js';
5
5
  /**
6
6
  * React hook for executing transactions
@@ -204,16 +204,10 @@ export function useTransaction({ walletClient, connector, solanaConnector, solan
204
204
  const chainId = transactionParams.chainId ?? 1;
205
205
  // Ensure correct chain
206
206
  const wallet = await ensureChain(chainId, walletClient, connector);
207
- // Create public client for the same chain
207
+ // Create public client with RPC fallback configuration
208
208
  // Use wallet's chain if available, otherwise look up chain by ID
209
209
  const chain = wallet.chain || getChainById(chainId);
210
- if (!chain) {
211
- throw new Error(`Unsupported chain ID: ${chainId}. Please ensure the chain is supported.`);
212
- }
213
- const publicClient = createPublicClient({
214
- chain,
215
- transport: http(),
216
- });
210
+ const publicClient = createPublicClientWithRpc(chainId, chain);
217
211
  setCurrentStep('Sending transaction');
218
212
  onStatus?.('Sending transaction');
219
213
  // Execute transaction
@@ -269,16 +263,10 @@ export function useTransaction({ walletClient, connector, solanaConnector, solan
269
263
  try {
270
264
  // Switch to source chain for approval
271
265
  const wallet = await ensureChain(chainId, walletClient, connector);
272
- // Check current allowance
266
+ // Create public client with RPC fallback configuration
273
267
  // Use wallet's chain if available, otherwise look up chain by ID
274
268
  const chain = wallet.chain || getChainById(chainId);
275
- if (!chain) {
276
- throw new Error(`Unsupported chain ID: ${chainId}. Please ensure the chain is supported.`);
277
- }
278
- const publicClient = createPublicClient({
279
- chain,
280
- transport: http(),
281
- });
269
+ const publicClient = createPublicClientWithRpc(chainId, chain);
282
270
  const currentAllowance = (await publicClient.readContract({
283
271
  address: tokenAddress,
284
272
  abi: erc20Abi,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silentswap/react",
3
3
  "type": "module",
4
- "version": "0.0.43",
4
+ "version": "0.0.45",
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.43",
27
- "@silentswap/ui-kit": "0.0.43",
26
+ "@silentswap/sdk": "0.0.45",
27
+ "@silentswap/ui-kit": "0.0.45",
28
28
  "@solana/codecs-strings": "^5.1.0",
29
29
  "@solana/kit": "^5.1.0",
30
30
  "@solana/rpc": "^5.1.0",