@silentswap/react 0.1.53 → 0.1.55

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.
@@ -9,6 +9,8 @@ export interface TronWalletConnector {
9
9
  sendTransaction: (tx: BridgeTransaction) => Promise<string>;
10
10
  getAccounts: () => Promise<string[]>;
11
11
  currentAccount?: string | null;
12
+ /** Wait for a transaction to be confirmed on-chain (polls tronWeb.trx.getTransactionInfo) */
13
+ waitForConfirmation?: (txHash: string) => Promise<void>;
12
14
  }
13
15
  /**
14
16
  * Tron connection interface
@@ -335,7 +335,8 @@ export function useBridgeExecution(walletClient, connector, solanaConnector, sol
335
335
  },
336
336
  }),
337
337
  });
338
- const usdIn = debridgeQuote.estimation?.srcChainTokenIn?.approximateUsdValue || 0;
338
+ const usdIn = debridgeQuote.estimation?.srcChainTokenIn?.originApproximateUsdValue
339
+ ?? debridgeQuote.estimation?.srcChainTokenIn?.approximateUsdValue ?? 0;
339
340
  const usdOut = debridgeQuote.estimation?.dstChainTokenOut?.approximateUsdValue || 0;
340
341
  const impactPercent = usdIn > 0 ? 100 * (1 - usdOut / usdIn) : 0;
341
342
  if (impactPercent > X_MAX_IMPACT_PERCENT) {
@@ -785,7 +786,15 @@ export function useBridgeExecution(walletClient, connector, solanaConnector, sol
785
786
  setCurrentStep(label);
786
787
  onStatus?.(label);
787
788
  const tronTx = convertRelayTronStepToTransaction(itemData, N_RELAY_CHAIN_ID_TRON);
788
- await tronExecutor(tronTx);
789
+ const txHash = await tronExecutor(tronTx);
790
+ // Wait for on-chain confirmation after approve before sending deposit
791
+ // (mirrors EVM path: sendTransactionAndWait + APPROVE_POST_DELAY_MS)
792
+ if (step.id === 'approve' && txHash && tronConnector?.waitForConfirmation) {
793
+ setCurrentStep('Waiting for approval confirmation...');
794
+ onStatus?.('Waiting for approval confirmation...');
795
+ await tronConnector.waitForConfirmation(txHash);
796
+ await new Promise((resolve) => setTimeout(resolve, APPROVE_POST_DELAY_MS));
797
+ }
789
798
  }
790
799
  const requestId = relayQuoteTyped.steps.find((s) => s.requestId)?.requestId;
791
800
  if (!requestId) {
@@ -209,8 +209,21 @@ export function useWallet({ client, address, auth, walletClient, connector, allD
209
209
  return;
210
210
  }
211
211
  console.log('[useWallet:generateWallet] no cache, querying deposit count ...');
212
- // Query the actual deposit count from the blockchain
213
- const depositCount = await queryDepositCount(normalizedAddress, client.s0xGatewayAddress);
212
+ // Query the actual deposit count from the blockchain.
213
+ // If every public RPC fallback fails (e.g. in-app browser blocks all of
214
+ // them), don't bail out of wallet generation — treat the user as a
215
+ // new user (depositCount = 0). Worst case they won't see historical
216
+ // facilitator accounts, but they can still sign up and swap. The
217
+ // alternative is a hard failure before any signature prompt, which
218
+ // strands the user with zero explanation.
219
+ let depositCount;
220
+ try {
221
+ depositCount = await queryDepositCount(normalizedAddress, client.s0xGatewayAddress);
222
+ }
223
+ catch (rpcErr) {
224
+ console.warn('[useWallet:generateWallet] queryDepositCount failed, falling back to 0:', rpcErr instanceof Error ? rpcErr.message : rpcErr);
225
+ depositCount = 0n;
226
+ }
214
227
  console.log('[useWallet:generateWallet] depositCount', depositCount);
215
228
  // Generate new entropy
216
229
  console.log('[useWallet:generateWallet] generating entropy ...');
@@ -31,13 +31,17 @@ export function useOrderEstimates({ evmAddress, solAddress, tronAddress, bitcoin
31
31
  // Bitcoin source - use user's actual Bitcoin address when available
32
32
  return bitcoinAddress || SBTC_ADDR_BITCOIN_NATIVE;
33
33
  }
34
+ else if (sourceAsset.caip19.startsWith('tron:')) {
35
+ // Tron source - use actual Tron address (deBridge rejects dead/placeholder addresses for Tron)
36
+ return tronAddress || evmAddress || EVM_PHONY_ADDRESS;
37
+ }
34
38
  else {
35
39
  return evmAddress || EVM_PHONY_ADDRESS;
36
40
  }
37
41
  }
38
42
  // Default to EVM fallback if no source asset
39
43
  return EVM_PHONY_ADDRESS;
40
- }, [sourceAsset, solAddress, evmAddress, bitcoinAddress]);
44
+ }, [sourceAsset, solAddress, evmAddress, bitcoinAddress, tronAddress]);
41
45
  // For egress, we always start from Avalanche (EVM), so use EVM address
42
46
  // If evmAddress is undefined, use the phony EVM address as fallback
43
47
  // This ensures egress quotes always use an EVM address format (required for Avalanche origin)
@@ -46,6 +50,7 @@ export function useOrderEstimates({ evmAddress, solAddress, tronAddress, bitcoin
46
50
  // and one for egress (uses EVM address since egress always starts from Avalanche)
47
51
  const ingressQuote = useQuote({
48
52
  address: ingressAddress,
53
+ evmAddress: evmAddress || EVM_PHONY_ADDRESS,
49
54
  maxImpactPercent,
50
55
  });
51
56
  const egressQuote = useQuote({
@@ -1,8 +1,10 @@
1
1
  import type { BridgeProvider, RelayQuoteResponse, DeBridgeOrderResponse, SolveUsdcResult } from '@silentswap/sdk';
2
2
  import { type EstimateSample, type Estimate, type BridgeQuoteResult } from '@silentswap/sdk';
3
3
  export interface useQuoteOptions {
4
- /** User's address (EVM hex address or Solana base58 address) */
4
+ /** User's address (EVM hex address, Solana base58, or Tron base58 address) */
5
5
  address?: `0x${string}` | string;
6
+ /** EVM address for destination fields when source is non-EVM (Tron, Solana) */
7
+ evmAddress?: `0x${string}` | string;
6
8
  /** Maximum price impact percentage allowed (default from SDK constants) */
7
9
  maxImpactPercent?: number;
8
10
  /** Timeout for quote requests in milliseconds (default: 30000) */
@@ -74,4 +76,4 @@ export interface useQuoteReturn {
74
76
  * Hook for getting optimized bridge quotes with retention rate tracking
75
77
  * Implements the same functionality as estimate.ts from the original app
76
78
  */
77
- export declare function useQuote({ address, maxImpactPercent, forceProvider, }?: useQuoteOptions): useQuoteReturn;
79
+ export declare function useQuote({ address, evmAddress: evmAddressOption, maxImpactPercent, forceProvider, }?: useQuoteOptions): useQuoteReturn;
@@ -5,7 +5,7 @@ import { NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE
5
5
  * Hook for getting optimized bridge quotes with retention rate tracking
6
6
  * Implements the same functionality as estimate.ts from the original app
7
7
  */
8
- export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, forceProvider, } = {}) {
8
+ export function useQuote({ address, evmAddress: evmAddressOption, maxImpactPercent = X_MAX_IMPACT_PERCENT, forceProvider, } = {}) {
9
9
  const [isLoading, setIsLoading] = useState(false);
10
10
  const [error, setError] = useState(null);
11
11
  // Estimates cache (replaces H_ESTIMATES_INGRESS and H_ESTIMATES_EGRESS from original)
@@ -415,14 +415,18 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
415
415
  debridgeParams.dstChainOrderAuthorityAddress = EVM_PHONY_ADDRESS;
416
416
  }
417
417
  else if (isTronChain) {
418
- // Tron source requires Tron-format authority fields and estimate disabled
418
+ // Tron source requires Tron-format authority fields and estimate disabled.
419
+ // deBridge rejects dead/placeholder addresses for Tron (can't estimate energy/bandwidth).
419
420
  const tronAddr = userAddress.startsWith('T') ? userAddress : SB58_ADDR_TRON_DEAD;
421
+ const evmDst = evmAddressOption && typeof evmAddressOption === 'string' && evmAddressOption.startsWith('0x')
422
+ ? evmAddressOption
423
+ : EVM_PHONY_ADDRESS;
420
424
  debridgeParams.enableEstimate = false;
421
425
  debridgeParams.account = tronAddr;
422
426
  debridgeParams.srcChainOrderAuthorityAddress = tronAddr;
423
427
  debridgeParams.srcChainRefundAddress = tronAddr;
424
- debridgeParams.dstChainTokenOutRecipient = EVM_PHONY_ADDRESS;
425
- debridgeParams.dstChainOrderAuthorityAddress = EVM_PHONY_ADDRESS;
428
+ debridgeParams.dstChainTokenOutRecipient = evmDst;
429
+ debridgeParams.dstChainOrderAuthorityAddress = evmDst;
426
430
  }
427
431
  const quote = await fetchDebridgeOrder(debridgeParams, signal);
428
432
  return quote;
@@ -6,6 +6,8 @@ import { createBitcoinTransactionExecutor, convertRelayBitcoinStepToTransaction
6
6
  import { createTronTransactionExecutor, convertRelayTronStepToTransaction, isRelayTronStepData } from './silent/tron-transaction.js';
7
7
  import { N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_TRON, N_DEBRIDGE_CHAIN_ID_TRON } from '@silentswap/sdk';
8
8
  import { N_DEBRIDGE_CHAIN_ID_SOLANA } from '@silentswap/sdk';
9
+ /** Delay after Tron approve tx so nodes sync before the deposit tx (mirrors EVM APPROVE_POST_DELAY_MS). */
10
+ const TRON_APPROVE_POST_DELAY_MS = 7_000;
9
11
  /**
10
12
  * React hook for executing transactions
11
13
  *
@@ -230,6 +232,13 @@ export function useTransaction({ walletClient, connector, solanaConnector, solan
230
232
  const hash = await tronExecutor(tronTx);
231
233
  if (hash)
232
234
  txHashes.push(hash);
235
+ // Wait for on-chain confirmation after approve before sending deposit
236
+ if (step.id === 'approve' && hash && tronConnector?.waitForConfirmation) {
237
+ setCurrentStep('Waiting for approval confirmation...');
238
+ onStatus?.('Waiting for approval confirmation...');
239
+ await tronConnector.waitForConfirmation(hash);
240
+ await new Promise((resolve) => setTimeout(resolve, TRON_APPROVE_POST_DELAY_MS));
241
+ }
233
242
  }
234
243
  }
235
244
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silentswap/react",
3
3
  "type": "module",
4
- "version": "0.1.53",
4
+ "version": "0.1.55",
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.1.53",
28
- "@silentswap/ui-kit": "0.1.53",
27
+ "@silentswap/sdk": "0.1.55",
28
+ "@silentswap/ui-kit": "0.1.55",
29
29
  "@solana/codecs-strings": "^5.1.0",
30
30
  "@solana/kit": "^5.1.0",
31
31
  "@solana/rpc": "^5.1.0",