@silentswap/react 0.1.0 → 0.1.2

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.
@@ -193,6 +193,11 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
193
193
  return amountStr;
194
194
  });
195
195
  const outputs = destinations.map((dest, idx) => {
196
+ // Validate destination asset exists in the asset registry
197
+ // This prevents invalid CAIP-19 identifiers (e.g. erc20 with zero address) from reaching the quote API
198
+ if (!getAssetByCaip19(dest.asset)) {
199
+ throw new Error(`Unknown destination asset: ${dest.asset}. Asset not found in registry.`);
200
+ }
196
201
  const isDestSolana = isSolanaAsset(dest.asset);
197
202
  const isDestBitcoin = isBitcoinAsset(dest.asset);
198
203
  let asset;
@@ -272,6 +277,14 @@ export function useQuoteCalculation({ address, evmAddress, wallet, depositorAddr
272
277
  // - Using isEvmNativeToken() would incorrectly try to construct erc20:null
273
278
  const isNative = destParsed.isNative;
274
279
  const destChainId = destParsed.chainId;
280
+ // Reject ERC-20 tokens with the zero address — the zero address is not a valid
281
+ // ERC-20 contract. Native tokens should use slip44 namespace instead.
282
+ if (!isNative &&
283
+ destParsed.tokenAddress &&
284
+ /^0x0+$/.test(destParsed.tokenAddress)) {
285
+ throw new Error(`Invalid ERC-20 token address for destination ${idx}: zero address is not a valid token. ` +
286
+ `Use slip44 namespace for native tokens (e.g. eip155:${destChainId}/slip44:60).`);
287
+ }
275
288
  asset = isNative
276
289
  ? dest.asset
277
290
  : caip19FungibleEvmToken(destChainId, destParsed.tokenAddress);
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  export type PlatformHealthStatus = 'ON' | 'ONLINE' | 'PAUSED' | 'DEPOSITS_PAUSED' | 'OFF' | 'MAINTENANCE' | 'UNKNOWN';
3
- export declare const MAX_DEPOSIT_USD = 25000;
4
3
  export type PlatformHealthContextType = {
5
4
  platformHealth: PlatformHealthStatus | null;
6
5
  maximumDepositUusdc: string | undefined;
@@ -14,6 +13,8 @@ export type PlatformHealthContextType = {
14
13
  storage: Record<string, string> | undefined;
15
14
  formDisabled: boolean;
16
15
  trackingDisabled: boolean;
16
+ /** Effective maximum deposit in USD (min of admin cap and platform API cap), or null if no cap. */
17
+ effectiveMaxDepositUsd: number | null;
17
18
  validateDepositAmount: (usdAmount: string | number) => {
18
19
  valid: boolean;
19
20
  error?: string;
@@ -43,13 +44,19 @@ export type PlatformHealthProviderProps = {
43
44
  * If not provided, trackingDisabled will always be false in the context
44
45
  */
45
46
  onTrackingDisabledChange?: (disabled: boolean) => void;
47
+ /**
48
+ * Optional maximum deposit amount in USD, typically fetched from admin dashboard settings.
49
+ * If not provided (undefined), no frontend cap is enforced — only the platform
50
+ * API's own maximumDepositUusdc limit applies.
51
+ */
52
+ maxDepositUsd?: number;
46
53
  };
47
54
  /**
48
55
  * Provider that monitors platform health from SilentSwapContext (which calls useStatus
49
56
  * once with proId) and provides validation functions for deposit amounts, output limits,
50
57
  * and service fee rates.
51
58
  */
52
- export declare function PlatformHealthProvider({ children, onFormDisabledChange, onTrackingDisabledChange, }: PlatformHealthProviderProps): import("react/jsx-runtime").JSX.Element;
59
+ export declare function PlatformHealthProvider({ children, onFormDisabledChange, onTrackingDisabledChange, maxDepositUsd, }: PlatformHealthProviderProps): import("react/jsx-runtime").JSX.Element;
53
60
  /**
54
61
  * Hook to access platform health context
55
62
  */
@@ -3,14 +3,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import React, { createContext, useContext, useEffect, useMemo, useCallback } from 'react';
4
4
  import { useSilentSwap } from '../contexts/SilentSwapContext.js';
5
5
  import { BigNumber } from 'bignumber.js';
6
- export const MAX_DEPOSIT_USD = 25000;
7
6
  const PlatformHealthContext = createContext(undefined);
8
7
  /**
9
8
  * Provider that monitors platform health from SilentSwapContext (which calls useStatus
10
9
  * once with proId) and provides validation functions for deposit amounts, output limits,
11
10
  * and service fee rates.
12
11
  */
13
- export function PlatformHealthProvider({ children, onFormDisabledChange, onTrackingDisabledChange, }) {
12
+ export function PlatformHealthProvider({ children, onFormDisabledChange, onTrackingDisabledChange, maxDepositUsd, }) {
14
13
  // Consume status data from parent SilentSwapContext instead of calling useStatus again
15
14
  const { status } = useSilentSwap();
16
15
  const { platformHealth: statusPlatformHealth, maximumDepositUusdc, minimumDepositUusdc, outputLimit, serviceFeeRate, overheadUsd, identity, volume, liquidity, storage, } = status;
@@ -98,6 +97,13 @@ export function PlatformHealthProvider({ children, onFormDisabledChange, onTrack
98
97
  return 0.01;
99
98
  return rate;
100
99
  }, [serviceFeeRate]);
100
+ // Compute effective max deposit: min of admin cap and platform API cap, or null if neither is set
101
+ const effectiveMaxDepositUsd = useMemo(() => {
102
+ const platformMax = getMaximumDepositUsd();
103
+ if (maxDepositUsd != null && platformMax != null)
104
+ return Math.min(maxDepositUsd, platformMax);
105
+ return maxDepositUsd ?? platformMax ?? null;
106
+ }, [maxDepositUsd, getMaximumDepositUsd]);
101
107
  // Validate deposit amount against min/max limits
102
108
  const validateDepositAmount = useCallback((usdAmount) => {
103
109
  const amount = typeof usdAmount === 'string' ? parseFloat(usdAmount) : usdAmount;
@@ -105,15 +111,14 @@ export function PlatformHealthProvider({ children, onFormDisabledChange, onTrack
105
111
  return { valid: false, error: 'Amount must be greater than zero' };
106
112
  }
107
113
  const minUsd = getMinimumDepositUsd();
108
- const maxUsd = Math.min(MAX_DEPOSIT_USD, getMaximumDepositUsd() ?? MAX_DEPOSIT_USD);
109
114
  if (minUsd !== null && amount < minUsd) {
110
115
  return { valid: false, error: `Minimum value is $${minUsd.toFixed(2)}` };
111
116
  }
112
- if (maxUsd !== null && amount > maxUsd) {
113
- return { valid: false, error: `Maximum value is $${maxUsd.toFixed(2)}` };
117
+ if (effectiveMaxDepositUsd !== null && amount > effectiveMaxDepositUsd) {
118
+ return { valid: false, error: `Maximum value is $${effectiveMaxDepositUsd.toFixed(2)}` };
114
119
  }
115
120
  return { valid: true };
116
- }, [getMinimumDepositUsd, getMaximumDepositUsd]);
121
+ }, [getMinimumDepositUsd, effectiveMaxDepositUsd]);
117
122
  // Validate output count against limit
118
123
  const validateOutputCount = useCallback((count) => {
119
124
  if (outputLimit === null || outputLimit === undefined) {
@@ -144,6 +149,7 @@ export function PlatformHealthProvider({ children, onFormDisabledChange, onTrack
144
149
  storage,
145
150
  formDisabled,
146
151
  trackingDisabled,
152
+ effectiveMaxDepositUsd,
147
153
  validateDepositAmount,
148
154
  validateOutputCount,
149
155
  getMinimumDepositUsd,
@@ -162,6 +168,7 @@ export function PlatformHealthProvider({ children, onFormDisabledChange, onTrack
162
168
  storage,
163
169
  formDisabled,
164
170
  trackingDisabled,
171
+ effectiveMaxDepositUsd,
165
172
  validateDepositAmount,
166
173
  validateOutputCount,
167
174
  getMinimumDepositUsd,
@@ -194,11 +194,17 @@ const useSwapStore = create()(persist((set, get) => ({
194
194
  return false;
195
195
  },
196
196
  updateDestinationAsset: (index, asset) => {
197
+ const assetStr = String(asset);
198
+ // Validate that the asset CAIP-19 exists in the registry
199
+ if (!getAssetByCaip19(assetStr)) {
200
+ console.warn(`[useSwap] Ignoring unknown destination asset: ${assetStr}`);
201
+ return;
202
+ }
197
203
  set((state) => {
198
204
  return {
199
205
  destinations: state.destinations.map((dest, idx) => idx === index
200
206
  ? {
201
- asset: String(asset),
207
+ asset: assetStr,
202
208
  contact: String(dest.contact),
203
209
  amount: '',
204
210
  priceUsd: dest.priceUsd,
package/dist/index.d.ts CHANGED
@@ -29,7 +29,6 @@ export { useStatus } from './hooks/useStatus.js';
29
29
  export type { StatusResponse, UseStatusOptions } from './hooks/useStatus.js';
30
30
  export { PlatformHealthProvider, usePlatformHealthContext } from './hooks/usePlatformHealth.js';
31
31
  export type { PlatformHealthStatus, PlatformHealthContextType, PlatformHealthProviderProps, } from './hooks/usePlatformHealth.js';
32
- export { MAX_DEPOSIT_USD } from './hooks/usePlatformHealth.js';
33
32
  export { PlatformHealthMonitor, usePlatformHealthMonitor, } from './hooks/usePlatformHealthMonitor.js';
34
33
  export type { PlatformHealthMonitorProps } from './hooks/usePlatformHealthMonitor.js';
35
34
  export { useHiddenSwapFees } from './hooks/useHiddenSwapFees.js';
package/dist/index.js CHANGED
@@ -19,7 +19,6 @@ export { useSwap, getSourceAssetCaip19, X_RANGE_SLIDER_MIN_GAP, OUTPUT_LIMIT, DE
19
19
  export { useEgressEstimates } from './hooks/useEgressEstimates.js';
20
20
  export { useStatus } from './hooks/useStatus.js';
21
21
  export { PlatformHealthProvider, usePlatformHealthContext } from './hooks/usePlatformHealth.js';
22
- export { MAX_DEPOSIT_USD } from './hooks/usePlatformHealth.js';
23
22
  export { PlatformHealthMonitor, usePlatformHealthMonitor, } from './hooks/usePlatformHealthMonitor.js';
24
23
  export { useHiddenSwapFees } from './hooks/useHiddenSwapFees.js';
25
24
  export { useSlippageUsd } from './hooks/useSlippageUsd.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silentswap/react",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.1.2",
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.0",
28
- "@silentswap/ui-kit": "0.1.0",
27
+ "@silentswap/sdk": "0.1.2",
28
+ "@silentswap/ui-kit": "0.1.2",
29
29
  "@solana/codecs-strings": "^5.1.0",
30
30
  "@solana/kit": "^5.1.0",
31
31
  "@solana/rpc": "^5.1.0",