@silentswap/react 0.0.51 → 0.0.52

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.
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ export type PlatformHealthStatus = 'ON' | 'ONLINE' | 'PAUSED' | 'DEPOSITS_PAUSED' | 'OFF' | 'MAINTENANCE' | 'UNKNOWN';
3
+ export type PlatformHealthContextType = {
4
+ platformHealth: PlatformHealthStatus | null;
5
+ maximumDepositUusdc: string | undefined;
6
+ minimumDepositUusdc: string | undefined;
7
+ outputLimit: number | undefined;
8
+ serviceFeeRate: number | undefined;
9
+ overheadUsd: number | undefined;
10
+ formDisabled: boolean;
11
+ trackingDisabled: boolean;
12
+ validateDepositAmount: (usdAmount: string | number) => {
13
+ valid: boolean;
14
+ error?: string;
15
+ };
16
+ validateOutputCount: (count: number) => {
17
+ valid: boolean;
18
+ error?: string;
19
+ };
20
+ getMinimumDepositUsd: () => number | null;
21
+ getMaximumDepositUsd: () => number | null;
22
+ getServiceFeeRate: () => number | null;
23
+ };
24
+ export type PlatformHealthProviderProps = {
25
+ children: React.ReactNode;
26
+ /**
27
+ * Optional callback to update form disabled state in app state
28
+ * If not provided, formDisabled will always be false in the context
29
+ */
30
+ onFormDisabledChange?: (disabled: boolean) => void;
31
+ /**
32
+ * Optional callback to update tracking disabled state in app state
33
+ * If not provided, trackingDisabled will always be false in the context
34
+ */
35
+ onTrackingDisabledChange?: (disabled: boolean) => void;
36
+ };
37
+ /**
38
+ * Provider that monitors platform health from status API and provides validation functions
39
+ * for deposit amounts, output limits, and service fee rates
40
+ */
41
+ export declare function PlatformHealthProvider({ children, onFormDisabledChange, onTrackingDisabledChange, }: PlatformHealthProviderProps): import("react/jsx-runtime").JSX.Element;
42
+ /**
43
+ * Hook to access platform health context
44
+ */
45
+ export declare function usePlatformHealthContext(): PlatformHealthContextType;
@@ -0,0 +1,172 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import React, { createContext, useContext, useEffect, useMemo, useCallback } from 'react';
4
+ import { useStatus } from '../hooks/useStatus.js';
5
+ import { BigNumber } from 'bignumber.js';
6
+ const PlatformHealthContext = createContext(undefined);
7
+ /**
8
+ * Provider that monitors platform health from status API and provides validation functions
9
+ * for deposit amounts, output limits, and service fee rates
10
+ */
11
+ export function PlatformHealthProvider({ children, onFormDisabledChange, onTrackingDisabledChange, }) {
12
+ const { platformHealth: statusPlatformHealth, maximumDepositUusdc, minimumDepositUusdc, outputLimit, serviceFeeRate, overheadUsd, } = useStatus();
13
+ // Normalize platform health status
14
+ const platformHealth = useMemo(() => {
15
+ if (!statusPlatformHealth)
16
+ return null;
17
+ return statusPlatformHealth;
18
+ }, [statusPlatformHealth]);
19
+ // Track disabled states locally for context value
20
+ const [formDisabled, setFormDisabled] = React.useState(false);
21
+ const [trackingDisabled, setTrackingDisabled] = React.useState(false);
22
+ // Update app state based on platform health
23
+ useEffect(() => {
24
+ if (!platformHealth) {
25
+ // Default to enabled if no platform health info
26
+ const newFormDisabled = false;
27
+ const newTrackingDisabled = false;
28
+ setFormDisabled(newFormDisabled);
29
+ setTrackingDisabled(newTrackingDisabled);
30
+ onFormDisabledChange?.(newFormDisabled);
31
+ onTrackingDisabledChange?.(newTrackingDisabled);
32
+ return;
33
+ }
34
+ // Update app state based on platform health (matching Svelte fees.ts logic)
35
+ let newFormDisabled = false;
36
+ let newTrackingDisabled = false;
37
+ switch (platformHealth) {
38
+ case 'ON':
39
+ case 'ONLINE':
40
+ // Everything enabled
41
+ newFormDisabled = false;
42
+ newTrackingDisabled = false;
43
+ break;
44
+ case 'PAUSED':
45
+ case 'DEPOSITS_PAUSED':
46
+ // Form disabled, tracking still enabled
47
+ newFormDisabled = true;
48
+ newTrackingDisabled = false;
49
+ break;
50
+ case 'OFF':
51
+ case 'MAINTENANCE':
52
+ case 'UNKNOWN':
53
+ default:
54
+ // Both form and tracking disabled
55
+ newFormDisabled = true;
56
+ newTrackingDisabled = true;
57
+ break;
58
+ }
59
+ setFormDisabled(newFormDisabled);
60
+ setTrackingDisabled(newTrackingDisabled);
61
+ onFormDisabledChange?.(newFormDisabled);
62
+ onTrackingDisabledChange?.(newTrackingDisabled);
63
+ }, [platformHealth, onFormDisabledChange, onTrackingDisabledChange]);
64
+ // Convert uusdc (micro-USDC) to USDC: 1 USDC = 1,000,000 uusdc
65
+ const getMinimumDepositUsd = useCallback(() => {
66
+ if (!minimumDepositUusdc)
67
+ return null;
68
+ try {
69
+ const uusdc = BigNumber(minimumDepositUusdc);
70
+ // Convert from micro-USDC to USDC (divide by 1e6)
71
+ return uusdc.dividedBy(1000000).toNumber();
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }, [minimumDepositUusdc]);
77
+ const getMaximumDepositUsd = useCallback(() => {
78
+ if (!maximumDepositUusdc)
79
+ return null;
80
+ try {
81
+ const uusdc = BigNumber(maximumDepositUusdc);
82
+ // Convert from micro-USDC to USDC (divide by 1e6)
83
+ return uusdc.dividedBy(1000000).toNumber();
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }, [maximumDepositUusdc]);
89
+ const getServiceFeeRate = useCallback(() => {
90
+ if (!serviceFeeRate)
91
+ return null;
92
+ try {
93
+ return +serviceFeeRate;
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }, [serviceFeeRate]);
99
+ // Validate deposit amount against min/max limits
100
+ const validateDepositAmount = useCallback((usdAmount) => {
101
+ const amount = typeof usdAmount === 'string' ? parseFloat(usdAmount) : usdAmount;
102
+ if (isNaN(amount) || amount <= 0) {
103
+ return { valid: false, error: 'Amount must be greater than zero' };
104
+ }
105
+ const minUsd = getMinimumDepositUsd();
106
+ const maxUsd = getMaximumDepositUsd();
107
+ if (minUsd !== null && amount < minUsd) {
108
+ return { valid: false, error: `Minimum deposit is $${minUsd.toFixed(2)}` };
109
+ }
110
+ if (maxUsd !== null && amount > maxUsd) {
111
+ return { valid: false, error: `Maximum deposit is $${maxUsd.toFixed(2)}` };
112
+ }
113
+ return { valid: true };
114
+ }, [getMinimumDepositUsd, getMaximumDepositUsd]);
115
+ // Validate output count against limit
116
+ const validateOutputCount = useCallback((count) => {
117
+ if (outputLimit === null || outputLimit === undefined) {
118
+ // No limit set, allow any count
119
+ return { valid: true };
120
+ }
121
+ if (count < 1) {
122
+ return { valid: false, error: 'At least one output destination is required' };
123
+ }
124
+ if (count > outputLimit) {
125
+ return {
126
+ valid: false,
127
+ error: `Maximum ${outputLimit} output destination${outputLimit === 1 ? '' : 's'} allowed`,
128
+ };
129
+ }
130
+ return { valid: true };
131
+ }, [outputLimit]);
132
+ const value = useMemo(() => ({
133
+ platformHealth,
134
+ maximumDepositUusdc,
135
+ minimumDepositUusdc,
136
+ outputLimit: outputLimit ?? undefined,
137
+ serviceFeeRate: serviceFeeRate ?? undefined,
138
+ overheadUsd: overheadUsd ?? undefined,
139
+ formDisabled,
140
+ trackingDisabled,
141
+ validateDepositAmount,
142
+ validateOutputCount,
143
+ getMinimumDepositUsd,
144
+ getMaximumDepositUsd,
145
+ getServiceFeeRate,
146
+ }), [
147
+ platformHealth,
148
+ maximumDepositUusdc,
149
+ minimumDepositUusdc,
150
+ outputLimit,
151
+ serviceFeeRate,
152
+ overheadUsd,
153
+ formDisabled,
154
+ trackingDisabled,
155
+ validateDepositAmount,
156
+ validateOutputCount,
157
+ getMinimumDepositUsd,
158
+ getMaximumDepositUsd,
159
+ getServiceFeeRate,
160
+ ]);
161
+ return _jsx(PlatformHealthContext.Provider, { value: value, children: children });
162
+ }
163
+ /**
164
+ * Hook to access platform health context
165
+ */
166
+ export function usePlatformHealthContext() {
167
+ const context = useContext(PlatformHealthContext);
168
+ if (context === undefined) {
169
+ throw new Error('usePlatformHealthContext must be used within a PlatformHealthProvider');
170
+ }
171
+ return context;
172
+ }
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ export type PlatformHealthMonitorProps = {
3
+ /**
4
+ * Component to render when maintenance mode is active
5
+ * Receives `enabled` prop indicating if maintenance mode is active
6
+ */
7
+ MaintenanceComponent: React.ComponentType<{
8
+ enabled: boolean;
9
+ }>;
10
+ };
11
+ /**
12
+ * Hook that determines if platform is in maintenance mode
13
+ * Returns the maintenance status based on platform health
14
+ */
15
+ export declare function usePlatformHealthMonitor(): {
16
+ isMaintenanceMode: boolean;
17
+ platformHealth: import("./usePlatformHealth.js").PlatformHealthStatus | null;
18
+ };
19
+ /**
20
+ * Component that renders MaintenanceComponent when platform is down for maintenance
21
+ * Should be mounted at the root level to ensure it runs on every page
22
+ * The actual platform health monitoring is done in PlatformHealthProvider
23
+ */
24
+ export declare function PlatformHealthMonitor({ MaintenanceComponent }: PlatformHealthMonitorProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { usePlatformHealthContext } from './usePlatformHealth.js';
4
+ /**
5
+ * Hook that determines if platform is in maintenance mode
6
+ * Returns the maintenance status based on platform health
7
+ */
8
+ export function usePlatformHealthMonitor() {
9
+ const { platformHealth } = usePlatformHealthContext();
10
+ // Show maintenance modal when status is 'OFF' or 'MAINTENANCE'
11
+ const isMaintenanceMode = platformHealth === 'OFF' || platformHealth === 'MAINTENANCE' || platformHealth === 'UNKNOWN';
12
+ return {
13
+ isMaintenanceMode,
14
+ platformHealth,
15
+ };
16
+ }
17
+ /**
18
+ * Component that renders MaintenanceComponent when platform is down for maintenance
19
+ * Should be mounted at the root level to ensure it runs on every page
20
+ * The actual platform health monitoring is done in PlatformHealthProvider
21
+ */
22
+ export function PlatformHealthMonitor({ MaintenanceComponent }) {
23
+ const { isMaintenanceMode } = usePlatformHealthMonitor();
24
+ return _jsx(MaintenanceComponent, { enabled: isMaintenanceMode });
25
+ }
package/dist/index.d.ts CHANGED
@@ -25,6 +25,10 @@ export { useEgressEstimates } from './hooks/useEgressEstimates.js';
25
25
  export type { UseEgressEstimatesOptions } from './hooks/useEgressEstimates.js';
26
26
  export { useStatus } from './hooks/useStatus.js';
27
27
  export type { StatusResponse } from './hooks/useStatus.js';
28
+ export { PlatformHealthProvider, usePlatformHealthContext } from './hooks/usePlatformHealth.js';
29
+ export type { PlatformHealthStatus, PlatformHealthContextType, PlatformHealthProviderProps, } from './hooks/usePlatformHealth.js';
30
+ export { PlatformHealthMonitor, usePlatformHealthMonitor, } from './hooks/usePlatformHealthMonitor.js';
31
+ export type { PlatformHealthMonitorProps } from './hooks/usePlatformHealthMonitor.js';
28
32
  export { useHiddenSwapFees } from './hooks/useHiddenSwapFees.js';
29
33
  export type { HiddenSwapFees, UseHiddenSwapFeesOptions } from './hooks/useHiddenSwapFees.js';
30
34
  export { useSlippageUsd } from './hooks/useSlippageUsd.js';
package/dist/index.js CHANGED
@@ -17,6 +17,8 @@ export { usePrices } from './hooks/usePrices.js';
17
17
  export { useSwap, getSourceAssetCaip19, X_RANGE_SLIDER_MIN_GAP, OUTPUT_LIMIT, DEFAULT_SOURCE_ASSET, DEFAULT_DEST_ASSET, } from './hooks/useSwap.js';
18
18
  export { useEgressEstimates } from './hooks/useEgressEstimates.js';
19
19
  export { useStatus } from './hooks/useStatus.js';
20
+ export { PlatformHealthProvider, usePlatformHealthContext } from './hooks/usePlatformHealth.js';
21
+ export { PlatformHealthMonitor, usePlatformHealthMonitor, } from './hooks/usePlatformHealthMonitor.js';
20
22
  export { useHiddenSwapFees } from './hooks/useHiddenSwapFees.js';
21
23
  export { useSlippageUsd } from './hooks/useSlippageUsd.js';
22
24
  export { useResetSwapForm } from './hooks/useResetSwapForm.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silentswap/react",
3
3
  "type": "module",
4
- "version": "0.0.51",
4
+ "version": "0.0.52",
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.51",
27
- "@silentswap/ui-kit": "0.0.51",
26
+ "@silentswap/sdk": "0.0.52",
27
+ "@silentswap/ui-kit": "0.0.52",
28
28
  "@solana/codecs-strings": "^5.1.0",
29
29
  "@solana/kit": "^5.1.0",
30
30
  "@solana/rpc": "^5.1.0",