@silentswap/react 0.0.41

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.
Files changed (86) hide show
  1. package/README.md +48 -0
  2. package/dist/contexts/AssetsContext.d.ts +24 -0
  3. package/dist/contexts/AssetsContext.js +83 -0
  4. package/dist/contexts/BalancesContext.d.ts +28 -0
  5. package/dist/contexts/BalancesContext.js +533 -0
  6. package/dist/contexts/OrdersContext.d.ts +53 -0
  7. package/dist/contexts/OrdersContext.js +240 -0
  8. package/dist/contexts/PricesContext.d.ts +12 -0
  9. package/dist/contexts/PricesContext.js +109 -0
  10. package/dist/contexts/SilentSwapContext.d.ts +58 -0
  11. package/dist/contexts/SilentSwapContext.js +205 -0
  12. package/dist/hooks/silent/orderTrackingWebSocketManager.d.ts +48 -0
  13. package/dist/hooks/silent/orderTrackingWebSocketManager.js +284 -0
  14. package/dist/hooks/silent/solana-transaction.d.ts +60 -0
  15. package/dist/hooks/silent/solana-transaction.js +236 -0
  16. package/dist/hooks/silent/useAuth.d.ts +90 -0
  17. package/dist/hooks/silent/useAuth.js +269 -0
  18. package/dist/hooks/silent/useBridgeExecution.d.ts +39 -0
  19. package/dist/hooks/silent/useBridgeExecution.js +877 -0
  20. package/dist/hooks/silent/useOrderSigning.d.ts +34 -0
  21. package/dist/hooks/silent/useOrderSigning.js +133 -0
  22. package/dist/hooks/silent/useOrderTracking.d.ts +174 -0
  23. package/dist/hooks/silent/useOrderTracking.js +524 -0
  24. package/dist/hooks/silent/useQuoteCalculation.d.ts +50 -0
  25. package/dist/hooks/silent/useQuoteCalculation.js +331 -0
  26. package/dist/hooks/silent/useQuoteFetching.d.ts +18 -0
  27. package/dist/hooks/silent/useQuoteFetching.js +54 -0
  28. package/dist/hooks/silent/useRefund.d.ts +26 -0
  29. package/dist/hooks/silent/useRefund.js +134 -0
  30. package/dist/hooks/silent/useSilentClient.d.ts +16 -0
  31. package/dist/hooks/silent/useSilentClient.js +32 -0
  32. package/dist/hooks/silent/useSilentOrders.d.ts +174 -0
  33. package/dist/hooks/silent/useSilentOrders.js +73 -0
  34. package/dist/hooks/silent/useSilentQuote.d.ts +88 -0
  35. package/dist/hooks/silent/useSilentQuote.js +381 -0
  36. package/dist/hooks/silent/useWallet.d.ts +76 -0
  37. package/dist/hooks/silent/useWallet.js +203 -0
  38. package/dist/hooks/useAssetPrice.d.ts +8 -0
  39. package/dist/hooks/useAssetPrice.js +47 -0
  40. package/dist/hooks/useContacts.d.ts +52 -0
  41. package/dist/hooks/useContacts.js +259 -0
  42. package/dist/hooks/useEgressEstimates.d.ts +32 -0
  43. package/dist/hooks/useEgressEstimates.js +230 -0
  44. package/dist/hooks/useHiddenSwapFees.d.ts +22 -0
  45. package/dist/hooks/useHiddenSwapFees.js +81 -0
  46. package/dist/hooks/useOrderEstimates.d.ts +37 -0
  47. package/dist/hooks/useOrderEstimates.js +393 -0
  48. package/dist/hooks/useOutputAssetInfo.d.ts +12 -0
  49. package/dist/hooks/useOutputAssetInfo.js +38 -0
  50. package/dist/hooks/usePrices.d.ts +60 -0
  51. package/dist/hooks/usePrices.js +188 -0
  52. package/dist/hooks/useQuote.d.ts +73 -0
  53. package/dist/hooks/useQuote.js +507 -0
  54. package/dist/hooks/useResetSwapForm.d.ts +16 -0
  55. package/dist/hooks/useResetSwapForm.js +68 -0
  56. package/dist/hooks/useSlippageUsd.d.ts +11 -0
  57. package/dist/hooks/useSlippageUsd.js +19 -0
  58. package/dist/hooks/useSolanaAdapter.d.ts +15 -0
  59. package/dist/hooks/useSolanaAdapter.js +55 -0
  60. package/dist/hooks/useStatus.d.ts +25 -0
  61. package/dist/hooks/useStatus.js +60 -0
  62. package/dist/hooks/useSwap.d.ts +67 -0
  63. package/dist/hooks/useSwap.js +285 -0
  64. package/dist/hooks/useTransaction.d.ts +119 -0
  65. package/dist/hooks/useTransaction.js +353 -0
  66. package/dist/hooks/useTransactionAddress.d.ts +11 -0
  67. package/dist/hooks/useTransactionAddress.js +26 -0
  68. package/dist/hooks/useUsdValue.d.ts +7 -0
  69. package/dist/hooks/useUsdValue.js +19 -0
  70. package/dist/index.d.ts +54 -0
  71. package/dist/index.js +41 -0
  72. package/dist/stories/SilentSwapOverview.stories.d.ts +10 -0
  73. package/dist/stories/SilentSwapOverview.stories.js +364 -0
  74. package/dist/stories/useAuth.stories.d.ts +6 -0
  75. package/dist/stories/useAuth.stories.js +55 -0
  76. package/dist/stories/useSilentClient.stories.d.ts +9 -0
  77. package/dist/stories/useSilentClient.stories.js +39 -0
  78. package/dist/stories/useSilentOrders.stories.d.ts +1 -0
  79. package/dist/stories/useSilentOrders.stories.js +1 -0
  80. package/dist/stories/useSilentQuote.stories.d.ts +6 -0
  81. package/dist/stories/useSilentQuote.stories.js +267 -0
  82. package/dist/stories/useTransaction.stories.d.ts +6 -0
  83. package/dist/stories/useTransaction.stories.js +121 -0
  84. package/dist/utils/formatters.d.ts +33 -0
  85. package/dist/utils/formatters.js +82 -0
  86. package/package.json +67 -0
@@ -0,0 +1,188 @@
1
+ import { useState, useCallback, useMemo } from 'react';
2
+ import BigNumber from 'bignumber.js';
3
+ // Global price cache (similar to Svelte's H_PRICES)
4
+ const priceCache = {};
5
+ const PRICE_CACHE_DURATION = 60 * 1000; // 60 seconds
6
+ const MAX_PRICE_AGE = 15 * 1000; // 15 seconds for fresh prices
7
+ // Mutex pool for preventing duplicate requests
8
+ const loadingMutexes = {};
9
+ /**
10
+ * React hook for fetching and caching asset prices from CoinGecko
11
+ *
12
+ * Provides price fetching functionality similar to the Svelte Asset.priceUsd() method
13
+ * with caching and batch fetching support.
14
+ *
15
+ * @param options - Configuration options
16
+ * @returns Object with price fetching methods and state
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { usePrices } from '@silentswap/react';
21
+ * import { getAssetByCaip19 } from '@silentswap/sdk';
22
+ *
23
+ * function MyComponent() {
24
+ * const { getPrice, getPrices } = usePrices();
25
+ *
26
+ * const handleGetPrice = async () => {
27
+ * const asset = getAssetByCaip19('eip155:1/erc20:0xA0b8...');
28
+ * if (asset) {
29
+ * const price = await getPrice(asset);
30
+ * console.log('Price:', price);
31
+ * }
32
+ * };
33
+ *
34
+ * return <button onClick={handleGetPrice}>Get Price</button>;
35
+ * }
36
+ * ```
37
+ */
38
+ export function usePrices(options = {}) {
39
+ const { maxPriceAge = MAX_PRICE_AGE, coingeckoApiKey = 'CG-QftACwuv13UVKqCnDdf4fkfn' } = options;
40
+ const [loadingPrices, setLoadingPrices] = useState(new Set());
41
+ // Get USD price for a single asset (similar to Asset.priceUsd())
42
+ const getPrice = useCallback(async (asset, maxAge = maxPriceAge) => {
43
+ const caip19 = asset.caip19;
44
+ // Check cache first
45
+ const cached = priceCache[caip19];
46
+ if (cached && cached.published + maxAge > Date.now()) {
47
+ return cached.priceUsd;
48
+ }
49
+ // Check if already loading - prevent double requests
50
+ if (!!loadingMutexes[caip19]) {
51
+ return loadingMutexes[caip19];
52
+ }
53
+ // Start loading - set mutex immediately to prevent race condition
54
+ setLoadingPrices((prev) => new Set(prev).add(caip19));
55
+ // Create and assign promise immediately to prevent concurrent requests
56
+ const pricePromise = (async () => {
57
+ try {
58
+ if (asset.coingeckoId) {
59
+ // Fetch from CoinGecko Pro API (same as Svelte)
60
+ const response = await fetch(`https://pro-api.coingecko.com/api/v3/simple/price?ids=${asset.coingeckoId}&vs_currencies=usd`, {
61
+ headers: {
62
+ 'X-CG-Pro-Api-Key': coingeckoApiKey,
63
+ },
64
+ signal: AbortSignal.timeout(30 * 1000),
65
+ });
66
+ if (response.ok) {
67
+ const data = await response.json();
68
+ const price = data[asset.coingeckoId]?.usd || 0;
69
+ // Cache the price
70
+ priceCache[caip19] = {
71
+ priceUsd: price,
72
+ published: Date.now(),
73
+ expiration: Date.now() + PRICE_CACHE_DURATION,
74
+ source: 'coingecko',
75
+ };
76
+ // Also cache for other assets with same CoinGecko ID
77
+ // (Note: This would require access to all assets, which we don't have here)
78
+ // The Svelte version does this, but for simplicity we'll just cache this asset
79
+ return price;
80
+ }
81
+ }
82
+ // Fallback: retry after delay
83
+ await new Promise((resolve) => setTimeout(resolve, 10 * 1000));
84
+ return getPrice(asset, maxAge);
85
+ }
86
+ catch (error) {
87
+ console.warn(`Failed to fetch price for ${caip19}:`, error);
88
+ // Fallback: retry after delay
89
+ await new Promise((resolve) => setTimeout(resolve, 10 * 1000));
90
+ return getPrice(asset, maxAge);
91
+ }
92
+ finally {
93
+ delete loadingMutexes[caip19];
94
+ setLoadingPrices((prev) => {
95
+ const next = new Set(prev);
96
+ next.delete(caip19);
97
+ return next;
98
+ });
99
+ }
100
+ })();
101
+ // Assign mutex BEFORE returning to prevent race condition
102
+ loadingMutexes[caip19] = pricePromise;
103
+ return pricePromise;
104
+ }, [maxPriceAge, coingeckoApiKey]);
105
+ // Get prices for multiple assets (batch fetch, similar to asset_prices())
106
+ const getPrices = useCallback(async (assets, maxAge = maxPriceAge) => {
107
+ const prices = [];
108
+ // Group by CoinGecko ID for batch requests
109
+ const coingeckoGroups = {};
110
+ for (const asset of assets) {
111
+ if (asset.coingeckoId) {
112
+ if (!coingeckoGroups[asset.coingeckoId]) {
113
+ coingeckoGroups[asset.coingeckoId] = [];
114
+ }
115
+ coingeckoGroups[asset.coingeckoId].push(asset);
116
+ }
117
+ }
118
+ // Process each CoinGecko ID group
119
+ const coingeckoIds = Object.keys(coingeckoGroups);
120
+ if (coingeckoIds.length > 0) {
121
+ try {
122
+ const response = await fetch(`https://pro-api.coingecko.com/api/v3/simple/price?ids=${coingeckoIds.join(',')}&vs_currencies=usd`, {
123
+ headers: {
124
+ 'X-CG-Pro-Api-Key': coingeckoApiKey,
125
+ },
126
+ signal: AbortSignal.timeout(30 * 1000),
127
+ });
128
+ if (response.ok) {
129
+ const data = await response.json();
130
+ // Update cache for all returned prices
131
+ for (const [coingeckoId, priceData] of Object.entries(data)) {
132
+ const price = priceData.usd || 0;
133
+ const groupAssets = coingeckoGroups[coingeckoId];
134
+ groupAssets.forEach((asset) => {
135
+ priceCache[asset.caip19] = {
136
+ priceUsd: price,
137
+ published: Date.now(),
138
+ expiration: Date.now() + PRICE_CACHE_DURATION,
139
+ source: 'coingecko',
140
+ };
141
+ });
142
+ }
143
+ }
144
+ }
145
+ catch (error) {
146
+ console.warn('Failed to batch fetch prices:', error);
147
+ }
148
+ }
149
+ // Return prices from cache (or 0 if not available)
150
+ return assets.map((asset) => {
151
+ const cached = priceCache[asset.caip19];
152
+ return cached && cached.published + maxAge > Date.now() ? cached.priceUsd : 0;
153
+ });
154
+ }, [maxPriceAge, coingeckoApiKey]);
155
+ // Get USD value for atomic units (similar to Asset.unitValueUsd)
156
+ const getUnitValueUsd = useCallback(async (asset, amount) => {
157
+ const price = await getPrice(asset);
158
+ const humanAmount = Number(BigNumber(amount.toString()).shiftedBy(-asset.decimals));
159
+ return humanAmount * price;
160
+ }, [getPrice]);
161
+ // Get USD value for human-readable amounts (similar to Asset.wholeValueUsd)
162
+ const getWholeValueUsd = useCallback(async (asset, amount) => {
163
+ const price = await getPrice(asset);
164
+ return BigNumber(amount.toString()).times(price).toNumber();
165
+ }, [getPrice]);
166
+ // Check if price is loading
167
+ const isPriceLoading = useCallback((caip19) => {
168
+ return loadingPrices.has(caip19);
169
+ }, [loadingPrices]);
170
+ // Get cached price (without fetching)
171
+ const getCachedPrice = useCallback((caip19, maxAge = maxPriceAge) => {
172
+ const cached = priceCache[caip19];
173
+ if (cached && cached.published + maxAge > Date.now()) {
174
+ return cached.priceUsd;
175
+ }
176
+ return null;
177
+ }, [maxPriceAge]);
178
+ const loadingPricesValue = useMemo(() => loadingPrices.size > 0, [loadingPrices]);
179
+ return {
180
+ getPrice,
181
+ getPrices,
182
+ getUnitValueUsd,
183
+ getWholeValueUsd,
184
+ isPriceLoading,
185
+ getCachedPrice,
186
+ loadingPrices: loadingPricesValue,
187
+ };
188
+ }
@@ -0,0 +1,73 @@
1
+ import type { BridgeProvider, RelayQuoteResponse, DeBridgeOrderResponse, SolveUsdcResult } from '@silentswap/sdk';
2
+ import { type EstimateSample, type Estimate, type BridgeQuoteResult } from '@silentswap/sdk';
3
+ export interface useQuoteOptions {
4
+ /** User's address (EVM hex address or Solana base58 address) */
5
+ address?: `0x${string}` | string;
6
+ /** Maximum price impact percentage allowed (default from SDK constants) */
7
+ maxImpactPercent?: number;
8
+ /** Timeout for quote requests in milliseconds (default: 30000) */
9
+ quoteTimeout?: number;
10
+ }
11
+ export type { RelayQuoteResponse, DeBridgeOrderResponse, SolveUsdcResult, EstimateSample, Estimate, BridgeQuoteResult, } from '@silentswap/sdk';
12
+ export type SolveResult = SolveUsdcResult;
13
+ /**
14
+ * Estimate result with quote details
15
+ */
16
+ export interface EstimateResult {
17
+ /** Estimate data with samples */
18
+ estimate: Estimate;
19
+ /** Amount of gas needed on source chain */
20
+ gasAmount: bigint;
21
+ /** Raw response from provider */
22
+ response: RelayQuoteResponse | DeBridgeOrderResponse;
23
+ /** Bridge provider used */
24
+ provider: BridgeProvider;
25
+ /** Calculated input amount for reverse calculation (output-to-input) */
26
+ calculatedInputAmount?: number;
27
+ }
28
+ export interface useQuoteReturn {
29
+ isLoading: boolean;
30
+ error: Error | null;
31
+ ingressEstimates: Record<string, Estimate>;
32
+ egressEstimates: Record<string, Estimate>;
33
+ /**
34
+ * Get quote for cross-chain swap
35
+ * @param srcChainId - Source chain ID
36
+ * @param srcToken - Source token address (0x0 for native)
37
+ * @param srcAmount - Source amount in token units (as string)
38
+ * @param dstChainId - Destination chain ID
39
+ * @param dstToken - Destination token address (0x0 for native)
40
+ * @param recipientAddress - Optional recipient address (required for Solana destinations)
41
+ * @param sourceAddress - Optional source chain address (for relay.link, must match source chain format)
42
+ * @returns Promise resolving to best quote with all details
43
+ */
44
+ getQuote: (srcChainId: number, srcToken: string, srcAmount: string, dstChainId: number, dstToken: string, recipientAddress?: string, sourceAddress?: string) => Promise<BridgeQuoteResult>;
45
+ /**
46
+ * Get live estimate for a given direction
47
+ * @param direction - 'ingress' (into Silent) or 'egress' (out of Silent)
48
+ * @param assetCaip19 - CAIP-19 asset identifier
49
+ * @param chainId - Chain ID
50
+ * @param tokenAddress - Token address (0x0 for native)
51
+ * @param amount - Amount in human-readable format
52
+ * @param usdPrice - USD price per token
53
+ * @param externalSignal - Optional abort signal
54
+ * @param recipientAddress - Optional recipient address (required for Solana destinations in egress)
55
+ * @param isReverseCalculation - For reverse calculation (output-to-input)
56
+ * @param targetAmount - Target amount for reverse calculation (output USD for ingress, output amount for egress)
57
+ * @returns Promise resolving to estimate result
58
+ */
59
+ estimateLive: (direction: 'ingress' | 'egress', assetCaip19: string, chainId: number | string, tokenAddress: string, amount: number, usdPrice: number, externalSignal?: AbortSignal, recipientAddress?: string, isReverseCalculation?: boolean, targetAmount?: number) => Promise<EstimateResult>;
60
+ /**
61
+ * Interpolate retention rate from samples
62
+ * @param samples - Array of estimate samples
63
+ * @param usdValue - USD value to interpolate for
64
+ * @param marginHi - Maximum margin above highest sample (default: Infinity)
65
+ * @returns Interpolated retention rate
66
+ */
67
+ interpolateSamples: (samples: EstimateSample[], usdValue: number, marginHi?: number) => number;
68
+ }
69
+ /**
70
+ * Hook for getting optimized bridge quotes with retention rate tracking
71
+ * Implements the same functionality as estimate.ts from the original app
72
+ */
73
+ export declare function useQuote({ address, maxImpactPercent }?: useQuoteOptions): useQuoteReturn;