@silentswap/react 0.0.98 → 0.1.1

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.
@@ -261,7 +261,6 @@ function SilentSwapInnerProvider({ children, client, evmAddress, solAddress, bit
261
261
  export function SilentSwapProvider({ children, client, evmAddress, solAddress, connector, isConnected, solanaConnector, solanaConnection, bitcoinConnector, bitcoinConnection, environment = ENVIRONMENT.STAGING, baseUrl, solanaRpcUrl, walletClient, bitcoinAddress, bitcoinRpcUrl, proId, requestWalletConnect, forceBridgeProvider, }) {
262
262
  const config = useMemo(() => {
263
263
  const computedBaseUrl = baseUrl ?? ENVIRONMENT_CONFIGS[environment].baseUrl;
264
- console.log('[SilentSwapProvider] Creating config:', { environment, baseUrl, computedBaseUrl });
265
264
  return {
266
265
  environment,
267
266
  baseUrl: computedBaseUrl,
@@ -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);
@@ -46,6 +46,10 @@ export function useWallet({ client, address, auth, walletClient, connector, allD
46
46
  const [wallet, setWallet] = useState(null);
47
47
  const [isLoading, setIsLoading] = useState(false);
48
48
  const [error, setError] = useState(null);
49
+ // Synchronous guard to prevent concurrent generateWallet calls.
50
+ // React state (isLoading) is async/batched, so multiple callers can see
51
+ // isLoading=false in the same tick and both trigger signTypedData prompts.
52
+ const isGeneratingRef = useRef(false);
49
53
  // Normalize address
50
54
  const normalizedAddress = address ? getAddress(address) : null;
51
55
  /**
@@ -112,6 +116,12 @@ export function useWallet({ client, address, auth, walletClient, connector, allD
112
116
  if (!normalizedAddress) {
113
117
  throw new Error('Address required for wallet generation');
114
118
  }
119
+ // Synchronous guard: prevent concurrent calls from racing through
120
+ // before React state (isLoading) has a chance to update
121
+ if (isGeneratingRef.current) {
122
+ return;
123
+ }
124
+ isGeneratingRef.current = true;
115
125
  setIsLoading(true);
116
126
  setError(null);
117
127
  try {
@@ -163,6 +173,7 @@ export function useWallet({ client, address, auth, walletClient, connector, allD
163
173
  throw error;
164
174
  }
165
175
  finally {
176
+ isGeneratingRef.current = false;
166
177
  setIsLoading(false);
167
178
  }
168
179
  }, [normalizedAddress, getCachedWallet, queryDepositCount, generateEntropy, allDeposits, connector, client.s0xGatewayAddress]);
@@ -180,6 +191,7 @@ export function useWallet({ client, address, auth, walletClient, connector, allD
180
191
  */
181
192
  const refreshWallet = useCallback(async () => {
182
193
  clearWallet();
194
+ isGeneratingRef.current = false;
183
195
  await generateWallet();
184
196
  }, [clearWallet, generateWallet]);
185
197
  // Clear wallet when address changes (e.g. user switched from MetaMask to Phantom)
@@ -1,6 +1,6 @@
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 = 35000;
3
+ export declare const MAX_DEPOSIT_USD = 25000;
4
4
  export type PlatformHealthContextType = {
5
5
  platformHealth: PlatformHealthStatus | null;
6
6
  maximumDepositUusdc: string | undefined;
@@ -3,7 +3,7 @@ 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 = 35000;
6
+ export const MAX_DEPOSIT_USD = 25000;
7
7
  const PlatformHealthContext = createContext(undefined);
8
8
  /**
9
9
  * Provider that monitors platform health from SilentSwapContext (which calls useStatus
@@ -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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silentswap/react",
3
3
  "type": "module",
4
- "version": "0.0.98",
4
+ "version": "0.1.1",
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.0.98",
28
- "@silentswap/ui-kit": "0.0.98",
27
+ "@silentswap/sdk": "0.1.1",
28
+ "@silentswap/ui-kit": "0.1.1",
29
29
  "@solana/codecs-strings": "^5.1.0",
30
30
  "@solana/kit": "^5.1.0",
31
31
  "@solana/rpc": "^5.1.0",