@silentswap/react 0.1.50 → 0.1.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.
- package/dist/contexts/AssetsContext.js +1 -0
- package/dist/contexts/BalancesContext.d.ts +3 -1
- package/dist/contexts/BalancesContext.js +235 -7
- package/dist/contexts/SilentSwapContext.d.ts +6 -1
- package/dist/contexts/SilentSwapContext.js +7 -4
- package/dist/hooks/silent/tron-transaction.d.ts +34 -4
- package/dist/hooks/silent/tron-transaction.js +45 -1
- package/dist/hooks/silent/useAuth.js +14 -0
- package/dist/hooks/silent/useBridgeExecution.d.ts +12 -2
- package/dist/hooks/silent/useBridgeExecution.js +341 -114
- package/dist/hooks/silent/useQuoteCalculation.d.ts +3 -1
- package/dist/hooks/silent/useQuoteCalculation.js +72 -5
- package/dist/hooks/silent/useSilentQuote.d.ts +8 -1
- package/dist/hooks/silent/useSilentQuote.js +77 -7
- package/dist/hooks/useContacts.d.ts +2 -2
- package/dist/hooks/useOrderEstimates.d.ts +3 -1
- package/dist/hooks/useOrderEstimates.js +23 -11
- package/dist/hooks/useQuote.js +53 -15
- package/dist/hooks/useTransaction.d.ts +6 -1
- package/dist/hooks/useTransaction.js +89 -8
- package/dist/hooks/useTransactionAddress.d.ts +3 -2
- package/dist/hooks/useTransactionAddress.js +10 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useState } from 'react';
|
|
2
|
-
import { isSolanaAsset, isBitcoinAsset, parseEvmCaip19, S_CAIP19_USDC_AVALANCHE, getAssetByCaip19, solveOptimalUsdcAmount, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, SB58_ADDR_SOL_PROGRAM_SYSTEM, isSolanaNativeToken, parseSolanaCaip19, EVM_PHONY_ADDRESS, isValidSolanaAddress, isValidBitcoinAddress, isValidEvmAddress, getAddressFromCaip10, S0X_ADDR_USDC_AVALANCHE, caip19FungibleEvmToken, FacilitatorKeyType, createHdFacilitatorGroupFromEntropy, PublicKeyArgGroups, SB58_CHAIN_ID_SOLANA_MAINNET, caip19SplToken, DeliveryMethod, X_MAX_IMPACT_PERCENT, SBTC_ADDR_BITCOIN_NATIVE, isEvmAsset, } from '@silentswap/sdk';
|
|
2
|
+
import { isSolanaAsset, isBitcoinAsset, isTronAsset, parseEvmCaip19, S_CAIP19_USDC_AVALANCHE, getAssetByCaip19, solveOptimalUsdcAmount, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_TRON, SB58_ADDR_SOL_PROGRAM_SYSTEM, isSolanaNativeToken, parseSolanaCaip19, parseTronCaip19, EVM_PHONY_ADDRESS, isValidSolanaAddress, isValidBitcoinAddress, isValidEvmAddress, isValidTronAddress, getAddressFromCaip10, S0X_ADDR_USDC_AVALANCHE, caip19FungibleEvmToken, FacilitatorKeyType, createHdFacilitatorGroupFromEntropy, PublicKeyArgGroups, SB58_CHAIN_ID_SOLANA_MAINNET, caip19SplToken, DeliveryMethod, X_MAX_IMPACT_PERCENT, SBTC_ADDR_BITCOIN_NATIVE, S0X_ADDR_TRON_NATIVE, isEvmAsset, } from '@silentswap/sdk';
|
|
3
3
|
import { getAddress } from 'viem';
|
|
4
4
|
import { BigNumber } from 'bignumber.js';
|
|
5
5
|
/**
|
|
@@ -13,7 +13,7 @@ import { BigNumber } from 'bignumber.js';
|
|
|
13
13
|
* - Destination amount updates
|
|
14
14
|
*/
|
|
15
15
|
// TODO: Simplify this hook by removing the useCallback and useState and just returning the calculateQuote function.
|
|
16
|
-
export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddress, getQuote, getPrice, setDestinations, proId, forceBridgeProvider, }) {
|
|
16
|
+
export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddress, getQuote, getPrice, setDestinations, proId, tronAddress, forceBridgeProvider, }) {
|
|
17
17
|
const [loadingAmounts, setLoadingAmounts] = useState(false);
|
|
18
18
|
const [depositAmountUsdc, setDepositAmountUsdc] = useState(0);
|
|
19
19
|
const calculateQuote = useCallback(async (debouncedSourceAsset, debouncedSourceAmount, destinations, splits) => {
|
|
@@ -30,6 +30,7 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
30
30
|
const isSourceUsdcAvalanche = debouncedSourceAsset === S_CAIP19_USDC_AVALANCHE;
|
|
31
31
|
const isSourceSolana = isSolanaAsset(debouncedSourceAsset);
|
|
32
32
|
const isSourceBitcoin = isBitcoinAsset(debouncedSourceAsset);
|
|
33
|
+
const isSourceTron = isTronAsset(debouncedSourceAsset);
|
|
33
34
|
let usdcAmountOut;
|
|
34
35
|
let sourceAmountInUnitsForQuote;
|
|
35
36
|
let bridgeProviderResult = 'none';
|
|
@@ -40,6 +41,7 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
40
41
|
isSourceUsdcAvalanche,
|
|
41
42
|
isSourceSolana,
|
|
42
43
|
isSourceBitcoin,
|
|
44
|
+
isSourceTron,
|
|
43
45
|
destinationsCount: destinations.length,
|
|
44
46
|
splits,
|
|
45
47
|
});
|
|
@@ -131,6 +133,31 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
131
133
|
bridgeProviderResult = solveResult.provider;
|
|
132
134
|
allowanceTargetResult = solveResult.allowanceTarget;
|
|
133
135
|
}
|
|
136
|
+
else if (isSourceTron) {
|
|
137
|
+
const assetInfo = getAssetByCaip19(debouncedSourceAsset);
|
|
138
|
+
if (!assetInfo)
|
|
139
|
+
throw new Error(`Tron asset not found`);
|
|
140
|
+
const tronParsed = parseTronCaip19(debouncedSourceAsset);
|
|
141
|
+
if (!tronParsed)
|
|
142
|
+
throw new Error(`Invalid Tron CAIP-19 format: ${debouncedSourceAsset}`);
|
|
143
|
+
const sourceAmountBN = BigNumber(debouncedSourceAmount);
|
|
144
|
+
sourceAmountInUnitsForQuote = sourceAmountBN.shiftedBy(assetInfo.decimals).toFixed(0);
|
|
145
|
+
if (!evmAddress) {
|
|
146
|
+
throw new Error('EVM address required for Tron swaps (needed for deposit calldata and recipient)');
|
|
147
|
+
}
|
|
148
|
+
const tronSenderAddress = typeof address === 'string' && !address.startsWith('0x') ? address : null;
|
|
149
|
+
if (!tronSenderAddress) {
|
|
150
|
+
throw new Error('Tron address required for Tron swaps');
|
|
151
|
+
}
|
|
152
|
+
const solveResult = await solveOptimalUsdcAmount(N_RELAY_CHAIN_ID_TRON, tronParsed.isNative ? S0X_ADDR_TRON_NATIVE : (tronParsed.tokenAddress || S0X_ADDR_TRON_NATIVE), sourceAmountInUnitsForQuote, tronSenderAddress, undefined, X_MAX_IMPACT_PERCENT, depositorAddress, getAddress(evmAddress), forceBridgeProvider);
|
|
153
|
+
if (abortController.signal.aborted) {
|
|
154
|
+
setLoadingAmounts(false);
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
usdcAmountOut = solveResult.usdcAmountOut.toString();
|
|
158
|
+
bridgeProviderResult = solveResult.provider;
|
|
159
|
+
allowanceTargetResult = solveResult.allowanceTarget;
|
|
160
|
+
}
|
|
134
161
|
else {
|
|
135
162
|
// EVM assets
|
|
136
163
|
const sourceAssetParsed = parseEvmCaip19(debouncedSourceAsset);
|
|
@@ -200,8 +227,9 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
200
227
|
}
|
|
201
228
|
const isDestSolana = isSolanaAsset(dest.asset);
|
|
202
229
|
const isDestBitcoin = isBitcoinAsset(dest.asset);
|
|
230
|
+
const isDestTron = isTronAsset(dest.asset);
|
|
203
231
|
let asset;
|
|
204
|
-
let recipientAddress; //
|
|
232
|
+
let recipientAddress; // Includes Solana, Bitcoin, Tron, and EVM addresses
|
|
205
233
|
if (isDestSolana) {
|
|
206
234
|
// Solana destination
|
|
207
235
|
const destParsed = parseSolanaCaip19(dest.asset);
|
|
@@ -265,6 +293,40 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
265
293
|
throw new Error(`Bitcoin destination ${idx} requires a recipient address in the contact field`);
|
|
266
294
|
}
|
|
267
295
|
}
|
|
296
|
+
else if (isDestTron) {
|
|
297
|
+
asset = dest.asset;
|
|
298
|
+
if (dest.contact) {
|
|
299
|
+
if (dest.contact.startsWith('caip10:tron:')) {
|
|
300
|
+
recipientAddress = getAddressFromCaip10(dest.contact);
|
|
301
|
+
if (!(isValidTronAddress(recipientAddress) && recipientAddress !== S0X_ADDR_TRON_NATIVE)) {
|
|
302
|
+
throw new Error(`Invalid Tron address extracted from CAIP10: ${dest.contact} -> ${recipientAddress}`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
else if (isValidTronAddress(dest.contact) && dest.contact !== S0X_ADDR_TRON_NATIVE) {
|
|
306
|
+
recipientAddress = dest.contact;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
if (tronAddress && isValidTronAddress(tronAddress) && tronAddress !== S0X_ADDR_TRON_NATIVE) {
|
|
310
|
+
console.warn(`[SilentSwap:QuoteCalc] Invalid Tron destination contact for index ${idx}, falling back to connected Tron address`, {
|
|
311
|
+
contact: dest.contact,
|
|
312
|
+
tronAddress,
|
|
313
|
+
});
|
|
314
|
+
recipientAddress = tronAddress;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
throw new Error(`Invalid Tron recipient address for destination ${idx}: ${dest.contact}. Expected Tron address or caip10:tron:*: format.`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
if (tronAddress && isValidTronAddress(tronAddress) && tronAddress !== S0X_ADDR_TRON_NATIVE) {
|
|
323
|
+
recipientAddress = tronAddress;
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
throw new Error(`Tron destination ${idx} requires a recipient address in the contact field`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
268
330
|
else {
|
|
269
331
|
// EVM destination (including XRPL which uses eip155 namespace)
|
|
270
332
|
const destParsed = parseEvmCaip19(dest.asset);
|
|
@@ -345,7 +407,12 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
345
407
|
throw new Error(`Invalid recipient address type for Bitcoin destination ${idx}: ${recipientAddress}. Expected Bitcoin address (bc1, 1, or 3 prefix).`);
|
|
346
408
|
}
|
|
347
409
|
}
|
|
348
|
-
else if (
|
|
410
|
+
else if (isDestTron) {
|
|
411
|
+
if (!(isValidTronAddress(recipientAddress) && recipientAddress !== S0X_ADDR_TRON_NATIVE)) {
|
|
412
|
+
throw new Error(`Invalid recipient address type for Tron destination ${idx}: ${recipientAddress}. Expected Tron address.`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
else if (!isDestSolana && !isDestBitcoin && !isDestTron) {
|
|
349
416
|
// Validate EVM address format
|
|
350
417
|
if (isEvmAsset(dest.asset) && !isValidEvmAddress(recipientAddress)) {
|
|
351
418
|
throw new Error(`Invalid recipient address type for EVM destination ${idx}: ${recipientAddress}. Expected 0x-prefixed EVM address.`);
|
|
@@ -460,7 +527,7 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
|
|
|
460
527
|
// Always ensure loading state is reset (safety net)
|
|
461
528
|
setLoadingAmounts(false);
|
|
462
529
|
}
|
|
463
|
-
}, [wallet, address, evmAddress, getQuote, getPrice, setDestinations, depositorAddress, proId]);
|
|
530
|
+
}, [wallet, address, evmAddress, getQuote, getPrice, setDestinations, depositorAddress, proId, tronAddress, forceBridgeProvider]);
|
|
464
531
|
return {
|
|
465
532
|
calculateQuote,
|
|
466
533
|
loadingAmounts,
|
|
@@ -3,6 +3,7 @@ import type { WalletClient } from 'viem';
|
|
|
3
3
|
import type { Connector } from 'wagmi';
|
|
4
4
|
import type { SolanaWalletConnector, SolanaConnection } from './solana-transaction.js';
|
|
5
5
|
import type { BitcoinWalletConnector, BitcoinConnection } from './bitcoin-transaction.js';
|
|
6
|
+
import type { TronWalletConnector, TronConnection } from './tron-transaction.js';
|
|
6
7
|
import { type SwapTransaction } from '../useTransaction.js';
|
|
7
8
|
import type { SilentSwapWallet } from './useWallet.js';
|
|
8
9
|
export type { SwapTransaction };
|
|
@@ -63,6 +64,12 @@ export interface useSilentQuoteOptions {
|
|
|
63
64
|
bitcoinConnector?: BitcoinWalletConnector;
|
|
64
65
|
/** Bitcoin connection (optional, for consistency) */
|
|
65
66
|
bitcoinConnection?: BitcoinConnection;
|
|
67
|
+
/** Tron wallet connector (required for Tron swaps) */
|
|
68
|
+
tronConnector?: TronWalletConnector;
|
|
69
|
+
/** Tron connection (optional, for consistency) */
|
|
70
|
+
tronConnection?: TronConnection;
|
|
71
|
+
/** Connected Tron address used for Tron destination recipient fallback. */
|
|
72
|
+
tronAddress?: string;
|
|
66
73
|
/** Get price function */
|
|
67
74
|
getPrice: (asset: AssetInfo) => Promise<number>;
|
|
68
75
|
setDestinations: (updater: Destination[] | ((prev: Destination[]) => Destination[])) => void;
|
|
@@ -105,4 +112,4 @@ export interface ExecuteSwapParams {
|
|
|
105
112
|
/** Optional integrator ID for tracking */
|
|
106
113
|
integratorId?: string;
|
|
107
114
|
}
|
|
108
|
-
export declare function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, auth, authenticate, wallet, walletLoading, walletError, generateWallet, requestWalletConnect, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, getPrice, setDestinations, proId, forceBridgeProvider, }: useSilentQuoteOptions): useSilentQuoteReturn;
|
|
115
|
+
export declare function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, auth, authenticate, wallet, walletLoading, walletError, generateWallet, requestWalletConnect, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, tronConnector, tronConnection, tronAddress, getPrice, setDestinations, proId, forceBridgeProvider, }: useSilentQuoteOptions): useSilentQuoteReturn;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useCallback, useMemo, useState, useRef, useEffect } from 'react';
|
|
2
|
-
import { hexToBase58, isSolanaAsset, isBitcoinAsset, parseEvmCaip19, S_CAIP19_USDC_AVALANCHE, NI_CHAIN_ID_AVALANCHE, } from '@silentswap/sdk';
|
|
2
|
+
import { hexToBase58, isSolanaAsset, isBitcoinAsset, isTronAsset, parseEvmCaip19, S_CAIP19_USDC_AVALANCHE, NI_CHAIN_ID_AVALANCHE, } from '@silentswap/sdk';
|
|
3
3
|
import { getAddress } from 'viem';
|
|
4
4
|
import { useQuoteFetching } from './useQuoteFetching.js';
|
|
5
5
|
import { useOrderSigning } from './useOrderSigning.js';
|
|
6
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
|
-
export function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, auth, authenticate, wallet, walletLoading = false, walletError = null, generateWallet, requestWalletConnect, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, getPrice, setDestinations, proId, forceBridgeProvider, }) {
|
|
9
|
+
export function useSilentQuote({ client, address, evmAddress, solAddress, walletClient, connector, auth, authenticate, wallet, walletLoading = false, walletError = null, generateWallet, requestWalletConnect, onStatus, solanaConnector, solanaConnection, solanaRpcUrl, bitcoinConnector, bitcoinConnection, tronConnector, tronConnection, tronAddress, getPrice, setDestinations, proId, forceBridgeProvider, }) {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
11
11
|
const [currentStep, setCurrentStep] = useState('');
|
|
12
12
|
const [quote, setQuote] = useState(null);
|
|
@@ -57,7 +57,7 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
57
57
|
// Initialize specialized hooks
|
|
58
58
|
const { getQuote: getQuoteInternal } = useQuoteFetching(client, rawAddress, setIsLoading, setCurrentStep, setError, onStatus);
|
|
59
59
|
const { signAuthorizations, createOrder } = useOrderSigning(walletClient, connector, client, setCurrentStep, onStatus);
|
|
60
|
-
const { executeSolanaBridge, executeBitcoinBridge, executeEvmBridge } = useBridgeExecution(walletClient, connector, solanaConnector, solanaConnection, solanaRpcUrl, setCurrentStep, depositorAddress, onStatus, bitcoinConnector, bitcoinConnection);
|
|
60
|
+
const { executeSolanaBridge, executeBitcoinBridge, executeTronBridge, executeEvmBridge } = useBridgeExecution(walletClient, connector, solanaConnector, solanaConnection, solanaRpcUrl, setCurrentStep, depositorAddress, onStatus, bitcoinConnector, bitcoinConnection, tronConnector, tronConnection);
|
|
61
61
|
const { executeSwapTransaction, approveTokenSpending } = useTransaction({
|
|
62
62
|
address: normalizedAddress || '0x0000000000000000000000000000000000000000',
|
|
63
63
|
walletClient,
|
|
@@ -65,6 +65,10 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
65
65
|
solanaConnector,
|
|
66
66
|
solanaConnection,
|
|
67
67
|
solanaRpcUrl,
|
|
68
|
+
bitcoinConnector,
|
|
69
|
+
bitcoinConnection,
|
|
70
|
+
tronConnector,
|
|
71
|
+
tronConnection,
|
|
68
72
|
setCurrentStep,
|
|
69
73
|
onStatus,
|
|
70
74
|
});
|
|
@@ -90,6 +94,7 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
90
94
|
getPrice,
|
|
91
95
|
setDestinations,
|
|
92
96
|
proId,
|
|
97
|
+
tronAddress,
|
|
93
98
|
forceBridgeProvider,
|
|
94
99
|
});
|
|
95
100
|
/**
|
|
@@ -268,8 +273,9 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
268
273
|
// Check swap type
|
|
269
274
|
const isSourceSolana = isSolanaAsset(sourceAsset);
|
|
270
275
|
const isSourceBitcoin = isBitcoinAsset(sourceAsset);
|
|
276
|
+
const isSourceTron = isTronAsset(sourceAsset);
|
|
271
277
|
const isDepositingDirectly = sourceAsset === S_CAIP19_USDC_AVALANCHE;
|
|
272
|
-
const isSourceEvm = !isSourceSolana && !isSourceBitcoin && !isDepositingDirectly && sourceAsset.startsWith('eip155:');
|
|
278
|
+
const isSourceEvm = !isSourceSolana && !isSourceBitcoin && !isSourceTron && !isDepositingDirectly && sourceAsset.startsWith('eip155:');
|
|
273
279
|
// Generate viewing authorization
|
|
274
280
|
const viewer = await resolvedGroup.viewer();
|
|
275
281
|
const evmSigner = await viewer.evmSigner();
|
|
@@ -292,7 +298,7 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
292
298
|
viewingAuth,
|
|
293
299
|
provider: providerForSwap,
|
|
294
300
|
});
|
|
295
|
-
const result = await executeSolanaSwap(quoteResponse, sourceAsset, sourceAmountInUnits, effectiveUsdcAmount, senderContactId, solanaConnector, evmSignerAddress, viewingAuth, createOrder, executeSolanaBridge, resolvedGroup, integratorId);
|
|
301
|
+
const result = await executeSolanaSwap(quoteResponse, sourceAsset, sourceAmountInUnits, effectiveUsdcAmount, senderContactId, solanaConnector, evmSignerAddress, viewingAuth, createOrder, executeSolanaBridge, resolvedGroup, providerForSwap, integratorId);
|
|
296
302
|
setOrderId(result.orderId);
|
|
297
303
|
setViewingAuth(result.viewingAuth);
|
|
298
304
|
return result;
|
|
@@ -306,6 +312,13 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
306
312
|
setViewingAuth(result.viewingAuth);
|
|
307
313
|
return result;
|
|
308
314
|
}
|
|
315
|
+
// Handle Tron swaps
|
|
316
|
+
if (isSourceTron) {
|
|
317
|
+
const result = await executeTronSwap(quoteResponse, sourceAsset, sourceAmountInUnits, effectiveUsdcAmount, senderContactId, tronConnector, evmSignerAddress, viewingAuth, createOrder, executeTronBridge, resolvedGroup, providerForSwap, integratorId);
|
|
318
|
+
setOrderId(result.orderId);
|
|
319
|
+
setViewingAuth(result.viewingAuth);
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
309
322
|
// Sign authorizations (for EVM swaps)
|
|
310
323
|
const signedAuths = await signAuthorizations(quoteResponse.authorizations, isDepositingDirectly);
|
|
311
324
|
// Create order with resolved facilitator group
|
|
@@ -389,10 +402,13 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
389
402
|
generateWallet,
|
|
390
403
|
solanaConnector,
|
|
391
404
|
bitcoinConnector,
|
|
405
|
+
tronConnector,
|
|
392
406
|
signAuthorizations,
|
|
393
407
|
createOrder,
|
|
394
408
|
approveTokenSpending,
|
|
395
409
|
executeSolanaBridge,
|
|
410
|
+
executeBitcoinBridge,
|
|
411
|
+
executeTronBridge,
|
|
396
412
|
executeEvmBridge,
|
|
397
413
|
executeSwapTransaction,
|
|
398
414
|
calculateQuote,
|
|
@@ -433,7 +449,7 @@ export function useSilentQuote({ client, address, evmAddress, solAddress, wallet
|
|
|
433
449
|
* 4. Returns swap result
|
|
434
450
|
*/
|
|
435
451
|
async function executeSolanaSwap(quoteResponse, sourceAsset, sourceAmount, usdcAmount, senderContactId, solanaConnector, evmSignerAddress, // EVM signer address (matches Svelte's s0x_signer)
|
|
436
|
-
viewingAuth, createOrder, executeSolanaBridge, facilitatorGroup, integratorId) {
|
|
452
|
+
viewingAuth, createOrder, executeSolanaBridge, facilitatorGroup, provider, integratorId) {
|
|
437
453
|
if (!solanaConnector) {
|
|
438
454
|
throw new Error('Solana connector required for Solana swaps');
|
|
439
455
|
}
|
|
@@ -489,7 +505,10 @@ viewingAuth, createOrder, executeSolanaBridge, facilitatorGroup, integratorId) {
|
|
|
489
505
|
depositParamsKeys: Object.keys(depositParams),
|
|
490
506
|
});
|
|
491
507
|
// Execute bridge transaction
|
|
492
|
-
const bridgeResult = await executeSolanaBridge(sourceAsset, sourceAmount, usdcAmount, solanaSenderAddress, evmSignerAddress,
|
|
508
|
+
const bridgeResult = await executeSolanaBridge(sourceAsset, sourceAmount, usdcAmount, solanaSenderAddress, evmSignerAddress, {
|
|
509
|
+
depositParams,
|
|
510
|
+
provider,
|
|
511
|
+
});
|
|
493
512
|
console.log('[SilentSwap:SolanaSwap] Bridge result', {
|
|
494
513
|
depositTxHash: bridgeResult.depositTxHash,
|
|
495
514
|
provider: bridgeResult.provider,
|
|
@@ -569,6 +588,57 @@ viewingAuth, createOrder, executeBitcoinBridge, facilitatorGroup, integratorId)
|
|
|
569
588
|
},
|
|
570
589
|
};
|
|
571
590
|
}
|
|
591
|
+
/**
|
|
592
|
+
* Execute Tron swap flow
|
|
593
|
+
*
|
|
594
|
+
* Handles the complete flow for Tron-based bridge swaps:
|
|
595
|
+
* 1. Validates Tron connection
|
|
596
|
+
* 2. Creates order (with empty authorizations for Tron)
|
|
597
|
+
* 3. Executes bridge transaction
|
|
598
|
+
* 4. Returns swap result
|
|
599
|
+
*/
|
|
600
|
+
async function executeTronSwap(quoteResponse, sourceAsset, sourceAmount, usdcAmount, senderContactId, tronConnector, evmSignerAddress, viewingAuth, createOrder, executeTronBridge, facilitatorGroup, provider, integratorId) {
|
|
601
|
+
if (!tronConnector) {
|
|
602
|
+
throw new Error('Tron connector required for Tron swaps');
|
|
603
|
+
}
|
|
604
|
+
const accounts = await tronConnector.getAccounts();
|
|
605
|
+
const tronSenderAddress = tronConnector.currentAccount || accounts[0] || '';
|
|
606
|
+
if (!tronSenderAddress) {
|
|
607
|
+
throw new Error('Failed to get Tron sender address');
|
|
608
|
+
}
|
|
609
|
+
const orderResponse = await createOrder(quoteResponse, quoteResponse.authorizations.map((auth) => ({
|
|
610
|
+
...auth,
|
|
611
|
+
signature: '0x',
|
|
612
|
+
})), {
|
|
613
|
+
sourceAsset: {
|
|
614
|
+
caip19: sourceAsset,
|
|
615
|
+
amount: `${BigInt(sourceAmount)}`,
|
|
616
|
+
},
|
|
617
|
+
sourceSender: {
|
|
618
|
+
contactId: senderContactId,
|
|
619
|
+
},
|
|
620
|
+
...(integratorId && { integratorId }),
|
|
621
|
+
}, facilitatorGroup);
|
|
622
|
+
const depositParams = orderResponse.transaction.metadata?.params;
|
|
623
|
+
if (!depositParams) {
|
|
624
|
+
throw new Error('Missing deposit parameters in order response');
|
|
625
|
+
}
|
|
626
|
+
const bridgeResult = await executeTronBridge(sourceAsset, sourceAmount, usdcAmount, tronSenderAddress, evmSignerAddress, {
|
|
627
|
+
depositParams,
|
|
628
|
+
provider,
|
|
629
|
+
});
|
|
630
|
+
const resultOrderId = orderResponse.response.orderId;
|
|
631
|
+
return {
|
|
632
|
+
orderId: resultOrderId,
|
|
633
|
+
viewingAuth,
|
|
634
|
+
depositTransaction: {
|
|
635
|
+
hash: bridgeResult.depositTxHash,
|
|
636
|
+
chainId: NI_CHAIN_ID_AVALANCHE,
|
|
637
|
+
status: 'confirmed',
|
|
638
|
+
confirmations: 1,
|
|
639
|
+
},
|
|
640
|
+
};
|
|
641
|
+
}
|
|
572
642
|
/**
|
|
573
643
|
* Execute EVM swap flow
|
|
574
644
|
*
|
|
@@ -16,7 +16,7 @@ export declare class AddressBookContact {
|
|
|
16
16
|
protected _s_caip10: string;
|
|
17
17
|
protected _s_ens: string;
|
|
18
18
|
protected _s_sns: string;
|
|
19
|
-
protected _s_caip2_ns: 'eip155' | 'solana' | 'bip122' | 'cosmos';
|
|
19
|
+
protected _s_caip2_ns: 'eip155' | 'solana' | 'bip122' | 'cosmos' | 'tron';
|
|
20
20
|
private _saveCallback?;
|
|
21
21
|
constructor(_g_info: AddressBookContactInfo, b_from_id?: boolean, saveCallback?: (contact: AddressBookContact) => void);
|
|
22
22
|
private updateENSRecord;
|
|
@@ -28,7 +28,7 @@ export declare class AddressBookContact {
|
|
|
28
28
|
get label(): string;
|
|
29
29
|
set label(s_label: string);
|
|
30
30
|
get source(): AddressBookContactSource;
|
|
31
|
-
get caip2Ns(): 'eip155' | 'solana' | 'bip122' | 'cosmos';
|
|
31
|
+
get caip2Ns(): 'eip155' | 'solana' | 'bip122' | 'cosmos' | 'tron';
|
|
32
32
|
isEvm(): boolean;
|
|
33
33
|
isSolana(): boolean;
|
|
34
34
|
isBip122(): boolean;
|
|
@@ -15,6 +15,8 @@ export interface UseOrderEstimatesOptions {
|
|
|
15
15
|
evmAddress?: `0x${string}`;
|
|
16
16
|
/** User's Solana address (base58 address) */
|
|
17
17
|
solAddress?: string;
|
|
18
|
+
/** User's Tron address (TVM base58 address) */
|
|
19
|
+
tronAddress?: string;
|
|
18
20
|
/** User's Bitcoin address */
|
|
19
21
|
bitcoinAddress?: string;
|
|
20
22
|
/** Source asset for determining which address to use (if Solana, use solAddress; if EVM, use evmAddress) */
|
|
@@ -32,7 +34,7 @@ export interface UseOrderEstimatesOptions {
|
|
|
32
34
|
*
|
|
33
35
|
* Returns retention rates that account for bridge fees and slippage
|
|
34
36
|
*/
|
|
35
|
-
export declare function useOrderEstimates({ evmAddress, solAddress, bitcoinAddress, sourceAsset, maxImpactPercent, }?: UseOrderEstimatesOptions): {
|
|
37
|
+
export declare function useOrderEstimates({ evmAddress, solAddress, tronAddress, bitcoinAddress, sourceAsset, maxImpactPercent, }?: UseOrderEstimatesOptions): {
|
|
36
38
|
estimateOrder: (usdcPrice: number, sourceAsset: AssetInfo, sourcePrice: number, sourceAmount: number | string, destinationAssets: AssetInfo[], destinationPrices: number[], splits: number[], calculationDirection?: CalculationDirection, outputAmounts?: string[], destinationContacts?: string[]) => Promise<OrderEstimateResult>;
|
|
37
39
|
isLoading: boolean;
|
|
38
40
|
error: Error | null;
|
|
@@ -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, isBitcoinAsset, EVM_PHONY_ADDRESS, SB58_ADDR_SOL_PROGRAM_SYSTEM, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, N_RELAY_CHAIN_ID_BITCOIN, SBTC_ADDR_BITCOIN_NATIVE, } from '@silentswap/sdk';
|
|
3
|
+
import { parseEvmCaip19, parseSolanaCaip19, parseTronCaip19, isEvmNativeToken, isSolanaNativeToken, isSolanaAsset, isBitcoinAsset, isTronAsset, EVM_PHONY_ADDRESS, SB58_ADDR_SOL_PROGRAM_SYSTEM, S0X_ADDR_TRON_NATIVE, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, N_RELAY_CHAIN_ID_BITCOIN, SBTC_ADDR_BITCOIN_NATIVE, } from '@silentswap/sdk';
|
|
4
4
|
import { useQuote } from './useQuote.js';
|
|
5
5
|
/**
|
|
6
6
|
* Hook for fetching both ingress and egress estimates in parallel
|
|
@@ -12,7 +12,7 @@ import { useQuote } from './useQuote.js';
|
|
|
12
12
|
*
|
|
13
13
|
* Returns retention rates that account for bridge fees and slippage
|
|
14
14
|
*/
|
|
15
|
-
export function useOrderEstimates({ evmAddress, solAddress, bitcoinAddress, sourceAsset, maxImpactPercent, } = {}) {
|
|
15
|
+
export function useOrderEstimates({ evmAddress, solAddress, tronAddress, bitcoinAddress, sourceAsset, maxImpactPercent, } = {}) {
|
|
16
16
|
const [error, setError] = useState(null);
|
|
17
17
|
const [isLoading, setIsLoading] = useState(false);
|
|
18
18
|
// Determine address for ingress quotes based on source chain
|
|
@@ -120,18 +120,23 @@ export function useOrderEstimates({ evmAddress, solAddress, bitcoinAddress, sour
|
|
|
120
120
|
console.log('[OrderEstimates] Step 3: Parsing source asset CAIP-19');
|
|
121
121
|
const isSourceSolana = isSolanaAsset(sourceAsset.caip19);
|
|
122
122
|
const isSourceBitcoin = isBitcoinAsset(sourceAsset.caip19);
|
|
123
|
-
const
|
|
123
|
+
const isSourceTron = isTronAsset(sourceAsset.caip19);
|
|
124
|
+
const sourceEvmParsed = !isSourceSolana && !isSourceBitcoin && !isSourceTron ? parseEvmCaip19(sourceAsset.caip19) : null;
|
|
124
125
|
const sourceSolanaParsed = isSourceSolana ? parseSolanaCaip19(sourceAsset.caip19) : null;
|
|
126
|
+
const sourceTronParsed = isSourceTron ? parseTronCaip19(sourceAsset.caip19) : null;
|
|
125
127
|
const sourceChainId = sourceEvmParsed?.chainId
|
|
126
128
|
?? sourceSolanaParsed?.chainId
|
|
129
|
+
?? sourceTronParsed?.chainId
|
|
127
130
|
?? (isSourceBitcoin ? N_RELAY_CHAIN_ID_BITCOIN : 0);
|
|
128
131
|
const sourceTokenAddress = isEvmNativeToken(sourceAsset.caip19)
|
|
129
132
|
? '0x0000000000000000000000000000000000000000'
|
|
130
133
|
: isSolanaNativeToken(sourceAsset.caip19)
|
|
131
134
|
? '11111111111111111111111111111111'
|
|
132
|
-
:
|
|
133
|
-
?
|
|
134
|
-
:
|
|
135
|
+
: isSourceTron
|
|
136
|
+
? (sourceTronParsed?.isNative ? S0X_ADDR_TRON_NATIVE : (sourceTronParsed?.tokenAddress ?? ''))
|
|
137
|
+
: isSourceBitcoin
|
|
138
|
+
? SBTC_ADDR_BITCOIN_NATIVE
|
|
139
|
+
: (sourceEvmParsed?.tokenAddress ?? sourceSolanaParsed?.tokenAddress ?? '');
|
|
135
140
|
console.log('[OrderEstimates] Step 3: Source asset parsed', { sourceChainId, sourceTokenAddress, isSourceSolana, isSourceBitcoin });
|
|
136
141
|
// For reverse calculation, calculate total output USD value first
|
|
137
142
|
let totalOutputUsd = 0;
|
|
@@ -184,18 +189,23 @@ export function useOrderEstimates({ evmAddress, solAddress, bitcoinAddress, sour
|
|
|
184
189
|
// Parse destination asset to get chain ID and token address from CAIP-19
|
|
185
190
|
const isDestSolana = isSolanaAsset(destAsset.caip19);
|
|
186
191
|
const isDestBitcoin = isBitcoinAsset(destAsset.caip19);
|
|
187
|
-
const
|
|
192
|
+
const isDestTron = isTronAsset(destAsset.caip19);
|
|
193
|
+
const destEvmParsed = !isDestSolana && !isDestBitcoin && !isDestTron ? parseEvmCaip19(destAsset.caip19) : null;
|
|
188
194
|
const destSolanaParsed = isDestSolana ? parseSolanaCaip19(destAsset.caip19) : null;
|
|
195
|
+
const destTronParsed = isDestTron ? parseTronCaip19(destAsset.caip19) : null;
|
|
189
196
|
const destChainId = destEvmParsed?.chainId
|
|
190
197
|
?? destSolanaParsed?.chainId
|
|
198
|
+
?? destTronParsed?.chainId
|
|
191
199
|
?? (isDestBitcoin ? N_RELAY_CHAIN_ID_BITCOIN : 0);
|
|
192
200
|
const destTokenAddress = isEvmNativeToken(destAsset.caip19)
|
|
193
201
|
? '0x0000000000000000000000000000000000000000'
|
|
194
202
|
: isSolanaNativeToken(destAsset.caip19)
|
|
195
203
|
? '11111111111111111111111111111111'
|
|
196
|
-
:
|
|
197
|
-
?
|
|
198
|
-
:
|
|
204
|
+
: isDestTron
|
|
205
|
+
? (destTronParsed?.isNative ? S0X_ADDR_TRON_NATIVE : (destTronParsed?.tokenAddress ?? ''))
|
|
206
|
+
: isDestBitcoin
|
|
207
|
+
? SBTC_ADDR_BITCOIN_NATIVE
|
|
208
|
+
: (destEvmParsed?.tokenAddress ?? destSolanaParsed?.tokenAddress ?? '');
|
|
199
209
|
// Determine recipient address based on destination chain
|
|
200
210
|
// Prefer the entered contact address (e.g. user-entered BTC address without wallet connected)
|
|
201
211
|
const contact = destinationContacts?.[idx];
|
|
@@ -203,7 +213,9 @@ export function useOrderEstimates({ evmAddress, solAddress, bitcoinAddress, sour
|
|
|
203
213
|
? (contact || solAddress)
|
|
204
214
|
: isDestBitcoin
|
|
205
215
|
? (contact || bitcoinAddress || SBTC_ADDR_BITCOIN_NATIVE)
|
|
206
|
-
:
|
|
216
|
+
: isDestTron
|
|
217
|
+
? (contact || tronAddress)
|
|
218
|
+
: (contact && contact.startsWith('0x') ? contact : evmAddress);
|
|
207
219
|
// For reverse calculation, use output amount directly with EXACT_OUTPUT
|
|
208
220
|
if (calculationDirection === CALCULATION_DIRECTION_OUTPUT_TO_INPUT && outputAmounts && outputAmounts[idx]) {
|
|
209
221
|
const outputAmount = parseFloat(outputAmounts[idx]);
|
package/dist/hooks/useQuote.js
CHANGED
|
@@ -1,8 +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, interpolateSamples as sdkInterpolateSamples, fetchRelayQuote, fetchDebridgeOrder, normalizeAddress, getAssetByCaip19, N_DEBRIDGE_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, SBTC_ADDR_BITCOIN_NATIVE, SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT, 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
|
-
// Constants for estimateLive
|
|
5
|
-
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
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, N_RELAY_CHAIN_ID_BITCOIN, SBTC_ADDR_BITCOIN_NATIVE, SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT, SB58_ADDR_SOL_PROGRAM_SYSTEM, S0X_ADDR_EVM_ZERO, S0X_ADDR_EVM_RELAY_LINK_DEAD, SB58_ADDR_SOL_RELAY_LINK_RECIPIENT, isSolanaAsset, isBitcoinAsset, isTronAsset, N_RELAY_CHAIN_ID_TRON, N_DEBRIDGE_CHAIN_ID_TRON, S0X_ADDR_TRON_NATIVE, SB58_ADDR_TRON_DEAD, EVM_PHONY_ADDRESS, } from '@silentswap/sdk';
|
|
6
4
|
/**
|
|
7
5
|
* Hook for getting optimized bridge quotes with retention rate tracking
|
|
8
6
|
* Implements the same functionality as estimate.ts from the original app
|
|
@@ -66,8 +64,8 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
66
64
|
try {
|
|
67
65
|
// Normalize addresses
|
|
68
66
|
console.log('[Quote] Step 2: Normalizing token addresses');
|
|
69
|
-
const srcTokenNorm = srcToken === '0x0' || srcToken ===
|
|
70
|
-
const dstTokenNorm = dstToken === '0x0' || dstToken ===
|
|
67
|
+
const srcTokenNorm = srcToken === '0x0' || srcToken === S0X_ADDR_EVM_ZERO ? S0X_ADDR_EVM_ZERO : srcToken;
|
|
68
|
+
const dstTokenNorm = dstToken === '0x0' || dstToken === S0X_ADDR_EVM_ZERO ? S0X_ADDR_EVM_ZERO : dstToken;
|
|
71
69
|
// Use shared quote fetching function
|
|
72
70
|
// normalizedAddress can be EVM (0x...) or Solana (base58) address
|
|
73
71
|
// sourceAddress is the address format for the source chain (for relay.link)
|
|
@@ -112,11 +110,12 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
112
110
|
isReverseCalculation,
|
|
113
111
|
targetAmount,
|
|
114
112
|
});
|
|
115
|
-
// Determine if this is a Solana or
|
|
113
|
+
// Determine if this is a Solana, Bitcoin, or Tron chain by checking the asset CAIP-19
|
|
116
114
|
// This is more reliable than checking chainId format
|
|
117
115
|
const isSolanaChain = isSolanaAsset(assetCaip19);
|
|
118
116
|
const isBitcoinChain = isBitcoinAsset(assetCaip19);
|
|
119
|
-
|
|
117
|
+
const isTronChain = isTronAsset(assetCaip19);
|
|
118
|
+
console.log('[Quote] Step 2: Chain type determined', { isSolanaChain, isBitcoinChain, isTronChain, chainId });
|
|
120
119
|
let numericChainId;
|
|
121
120
|
if (isSolanaChain) {
|
|
122
121
|
// For Solana, we'll use different chain IDs for different providers
|
|
@@ -127,6 +126,10 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
127
126
|
// Bitcoin uses the relay chain ID directly (only relay supports Bitcoin)
|
|
128
127
|
numericChainId = N_RELAY_CHAIN_ID_BITCOIN;
|
|
129
128
|
}
|
|
129
|
+
else if (isTronChain) {
|
|
130
|
+
// Tron uses different chain IDs per provider, set per-provider below
|
|
131
|
+
numericChainId = 0; // Placeholder, will be set per provider
|
|
132
|
+
}
|
|
130
133
|
else {
|
|
131
134
|
// For EVM chains, convert chainId to number if needed
|
|
132
135
|
if (typeof chainId === 'string') {
|
|
@@ -157,7 +160,7 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
157
160
|
try {
|
|
158
161
|
// Special case for USDC on Avalanche
|
|
159
162
|
// Check numericChainId (exclude non-EVM chains which use relay chain IDs)
|
|
160
|
-
const checkChainId = (isSolanaChain || isBitcoinChain) ? 0 : numericChainId;
|
|
163
|
+
const checkChainId = (isSolanaChain || isBitcoinChain || isTronChain) ? 0 : numericChainId;
|
|
161
164
|
if (checkChainId === NI_CHAIN_ID_AVALANCHE &&
|
|
162
165
|
tokenAddress.toLowerCase() === S0X_ADDR_USDC_AVALANCHE.toLowerCase()) {
|
|
163
166
|
console.log('[Quote] Step 3: Special case - USDC on Avalanche, returning identity estimate');
|
|
@@ -218,6 +221,12 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
218
221
|
? normalizedAddress
|
|
219
222
|
: SBTC_ADDR_BITCOIN_NATIVE;
|
|
220
223
|
}
|
|
224
|
+
else if (isTronChain) {
|
|
225
|
+
// For Tron ingress, use Tron address (starts with T) or dead address as fallback
|
|
226
|
+
userAddress = normalizedAddress && normalizedAddress.startsWith('T')
|
|
227
|
+
? normalizedAddress
|
|
228
|
+
: SB58_ADDR_TRON_DEAD;
|
|
229
|
+
}
|
|
221
230
|
else {
|
|
222
231
|
// For EVM ingress, use EVM address (or phony if not available)
|
|
223
232
|
userAddress = normalizedAddress && normalizedAddress.startsWith('0x')
|
|
@@ -231,11 +240,14 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
231
240
|
? normalizedAddress
|
|
232
241
|
: EVM_PHONY_ADDRESS;
|
|
233
242
|
}
|
|
234
|
-
// Map chain IDs per provider (Solana and
|
|
243
|
+
// Map chain IDs per provider (Solana, Bitcoin, and Tron use provider-specific IDs)
|
|
235
244
|
const relayChainId = isSolanaChain ? N_RELAY_CHAIN_ID_SOLANA
|
|
236
245
|
: isBitcoinChain ? N_RELAY_CHAIN_ID_BITCOIN
|
|
246
|
+
: isTronChain ? N_RELAY_CHAIN_ID_TRON
|
|
247
|
+
: numericChainId;
|
|
248
|
+
const debridgeChainId = isSolanaChain ? N_DEBRIDGE_CHAIN_ID_SOLANA
|
|
249
|
+
: isTronChain ? N_DEBRIDGE_CHAIN_ID_TRON
|
|
237
250
|
: numericChainId;
|
|
238
|
-
const debridgeChainId = isSolanaChain ? N_DEBRIDGE_CHAIN_ID_SOLANA : numericChainId;
|
|
239
251
|
console.log('[Quote] Step 4: Address and chain IDs determined', {
|
|
240
252
|
userAddress,
|
|
241
253
|
relayChainId,
|
|
@@ -279,7 +291,9 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
279
291
|
destinationChainId: NI_CHAIN_ID_AVALANCHE,
|
|
280
292
|
originCurrency: isBitcoinChain
|
|
281
293
|
? (tokenAddress || SBTC_ADDR_BITCOIN_NATIVE)
|
|
282
|
-
:
|
|
294
|
+
: isTronChain
|
|
295
|
+
? (tokenAddress || S0X_ADDR_TRON_NATIVE)
|
|
296
|
+
: (tokenAddress === S0X_ADDR_EVM_ZERO ? S0X_ADDR_EVM_ZERO : tokenAddress),
|
|
283
297
|
destinationCurrency: S0X_ADDR_USDC_AVALANCHE,
|
|
284
298
|
...(isReverseCalculation && tradeType === 'EXACT_OUTPUT'
|
|
285
299
|
? {
|
|
@@ -295,7 +309,9 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
295
309
|
? { recipient: EVM_PHONY_ADDRESS }
|
|
296
310
|
: isBitcoinChain
|
|
297
311
|
? { recipient: EVM_PHONY_ADDRESS }
|
|
298
|
-
:
|
|
312
|
+
: isTronChain
|
|
313
|
+
? { recipient: EVM_PHONY_ADDRESS }
|
|
314
|
+
: {}),
|
|
299
315
|
}
|
|
300
316
|
: {
|
|
301
317
|
originChainId: NI_CHAIN_ID_AVALANCHE,
|
|
@@ -303,7 +319,9 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
303
319
|
destinationChainId: relayChainId,
|
|
304
320
|
destinationCurrency: isBitcoinChain
|
|
305
321
|
? (tokenAddress || SBTC_ADDR_BITCOIN_NATIVE)
|
|
306
|
-
:
|
|
322
|
+
: isTronChain
|
|
323
|
+
? (tokenAddress || S0X_ADDR_TRON_NATIVE)
|
|
324
|
+
: (tokenAddress === S0X_ADDR_EVM_ZERO ? S0X_ADDR_EVM_ZERO : tokenAddress),
|
|
307
325
|
...(isReverseCalculation && tradeType === 'EXACT_OUTPUT'
|
|
308
326
|
? {
|
|
309
327
|
// For reverse egress: we specify the destination (output) amount
|
|
@@ -326,7 +344,14 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
326
344
|
? recipientAddress
|
|
327
345
|
: SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT,
|
|
328
346
|
}
|
|
329
|
-
:
|
|
347
|
+
: isTronChain
|
|
348
|
+
? {
|
|
349
|
+
// Tron egress: recipient must be a valid Tron address (starts with T)
|
|
350
|
+
recipient: recipientAddress && recipientAddress.startsWith('T')
|
|
351
|
+
? recipientAddress
|
|
352
|
+
: SB58_ADDR_TRON_DEAD,
|
|
353
|
+
}
|
|
354
|
+
: {}),
|
|
330
355
|
}),
|
|
331
356
|
}, signal);
|
|
332
357
|
return quote;
|
|
@@ -351,9 +376,12 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
351
376
|
return null; // Skip DeBridge for Bitcoin, will use Relay.link only
|
|
352
377
|
}
|
|
353
378
|
// For reverse calculation ingress: use srcChainTokenInAmount: 'auto' and specify dstChainTokenOutAmount
|
|
379
|
+
const srcTokenForDebridge = isTronChain
|
|
380
|
+
? (tokenAddress || S0X_ADDR_TRON_NATIVE)
|
|
381
|
+
: (tokenAddress === S0X_ADDR_EVM_ZERO ? S0X_ADDR_EVM_ZERO : tokenAddress);
|
|
354
382
|
const debridgeParams = {
|
|
355
383
|
srcChainId: debridgeChainId,
|
|
356
|
-
srcChainTokenIn:
|
|
384
|
+
srcChainTokenIn: srcTokenForDebridge,
|
|
357
385
|
dstChainId: NI_CHAIN_ID_AVALANCHE,
|
|
358
386
|
dstChainTokenOut: S0X_ADDR_USDC_AVALANCHE,
|
|
359
387
|
prependOperatingExpenses: true,
|
|
@@ -386,6 +414,16 @@ export function useQuote({ address, maxImpactPercent = X_MAX_IMPACT_PERCENT, for
|
|
|
386
414
|
debridgeParams.dstChainTokenOutRecipient = EVM_PHONY_ADDRESS;
|
|
387
415
|
debridgeParams.dstChainOrderAuthorityAddress = EVM_PHONY_ADDRESS;
|
|
388
416
|
}
|
|
417
|
+
else if (isTronChain) {
|
|
418
|
+
// Tron source requires Tron-format authority fields and estimate disabled
|
|
419
|
+
const tronAddr = userAddress.startsWith('T') ? userAddress : SB58_ADDR_TRON_DEAD;
|
|
420
|
+
debridgeParams.enableEstimate = false;
|
|
421
|
+
debridgeParams.account = tronAddr;
|
|
422
|
+
debridgeParams.srcChainOrderAuthorityAddress = tronAddr;
|
|
423
|
+
debridgeParams.srcChainRefundAddress = tronAddr;
|
|
424
|
+
debridgeParams.dstChainTokenOutRecipient = EVM_PHONY_ADDRESS;
|
|
425
|
+
debridgeParams.dstChainOrderAuthorityAddress = EVM_PHONY_ADDRESS;
|
|
426
|
+
}
|
|
389
427
|
const quote = await fetchDebridgeOrder(debridgeParams, signal);
|
|
390
428
|
return quote;
|
|
391
429
|
}
|