@silentswap/sdk 0.1.63 → 0.1.65

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/assets.d.ts CHANGED
@@ -27,7 +27,7 @@ export interface AssetsData {
27
27
  chains: Record<Caip2, ChainInfo>;
28
28
  assets: Record<Caip19, AssetInfo>;
29
29
  }
30
- export declare function loadAssetsData(): AssetsData;
30
+ export declare function loadAssetsData(): Promise<AssetsData>;
31
31
  export declare function getAllAssets(): Record<Caip19, AssetInfo>;
32
32
  export declare function getAllChains(): Record<Caip2, ChainInfo>;
33
33
  export declare function getAllAssetsArray(): AssetInfo[];
package/dist/assets.js CHANGED
@@ -1,10 +1,25 @@
1
- import filteredData from './data/filtered.json' with { type: 'json' };
1
+ // Lazy-loaded assets data avoids loading the 96KB JSON at module import time.
2
+ // Dynamic import works with Vite/webpack code-splitting; bundlers treat .json imports as modules.
3
+ let _filteredDataPromise = null;
4
+ async function getFilteredDataAsync() {
5
+ if (!_filteredDataPromise) {
6
+ _filteredDataPromise = import('./data/filtered.json').then((module) => (module.default ?? module));
7
+ }
8
+ return _filteredDataPromise;
9
+ }
10
+ // Synchronous accessor — returns cached data after loadAssetsData() resolves.
11
+ // Throws if data hasn't been loaded yet; callers should await loadAssetsData() first.
12
+ let _filteredData = null;
2
13
  function getFilteredData() {
3
- return filteredData;
14
+ if (!_filteredData) {
15
+ throw new Error('Assets data not loaded. Call loadAssetsData() first.');
16
+ }
17
+ return _filteredData;
4
18
  }
5
- // Load assets data from filtered.json
6
- export function loadAssetsData() {
7
- return getFilteredData();
19
+ // Load assets data from filtered.json (async — call once at app startup)
20
+ export async function loadAssetsData() {
21
+ _filteredData = await getFilteredDataAsync();
22
+ return _filteredData;
8
23
  }
9
24
  // Get all assets from the filtered data
10
25
  export function getAllAssets() {
package/dist/bridge.js CHANGED
@@ -2,6 +2,12 @@ import { encodeFunctionData, erc20Abi } from 'viem';
2
2
  import BigNumber from 'bignumber.js';
3
3
  import { NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, S0X_ADDR_EVM_ZERO, UINT256_MAX, N_DEBRIDGE_CHAIN_ID_SOLANA, N_DEBRIDGE_CHAIN_ID_TRON, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_SUI, N_RELAY_CHAIN_ID_TRON, S0X_ADDR_TRON_NATIVE, SB58_ADDR_SOL_PROGRAM_SYSTEM, } from './constants.js';
4
4
  import { createPhonyDepositCalldata } from './wallet.js';
5
+ // TTL cache for solveOptimalUsdcAmount — avoids re-fetching identical quotes
6
+ const QUOTE_CACHE_TTL = 30_000; // 30 seconds
7
+ const quoteCache = new Map();
8
+ function getQuoteCacheKey(srcChainId, srcToken, srcAmount, forceProvider) {
9
+ return `${srcChainId}:${srcToken}:${srcAmount}:${forceProvider ?? 'any'}`;
10
+ }
5
11
  /**
6
12
  * Map relay.link chain IDs to deBridge chain IDs
7
13
  * Different bridge providers use different chain ID schemes
@@ -349,7 +355,6 @@ export async function fetchDebridgeOrder(params, signal) {
349
355
  * Note: DLN does not support same-chain swaps via create-tx endpoint
350
356
  */
351
357
  async function fetchDebridgeSingleChainOrder(params, signal) {
352
- console.log('fetchDebridgeSingleChainOrder');
353
358
  // Build query parameters for single-chain swap endpoint
354
359
  const queryParams = new URLSearchParams({
355
360
  chainId: params.srcChainId.toString(),
@@ -359,6 +364,16 @@ async function fetchDebridgeSingleChainOrder(params, signal) {
359
364
  tokenOutRecipient: params.dstChainTokenOutRecipient || params.account || '',
360
365
  senderAddress: params.senderAddress || params.account || '',
361
366
  });
367
+ // EXACT_OUTPUT support: when caller passes a concrete dstChainTokenOutAmount
368
+ // (and srcChainTokenInAmount === 'auto'), forward it as `tokenOutAmount`.
369
+ // Without this the convergence loop in solveDebridgeSingleChainUsdcAmount
370
+ // sends `tokenInAmount=auto` with no target → deBridge returns
371
+ // INTERNAL_SERVER_ERROR on every iteration after the first, so the loop
372
+ // never finds the optimal price and surfaces as "Failed to find optimal
373
+ // bridge price".
374
+ if (params.dstChainTokenOutAmount && params.dstChainTokenOutAmount !== 'auto') {
375
+ queryParams.set('tokenOutAmount', params.dstChainTokenOutAmount);
376
+ }
362
377
  // Add optional parameters if provided
363
378
  if (params.prependOperatingExpenses !== undefined) {
364
379
  queryParams.set('prependOperatingExpenses', String(params.prependOperatingExpenses));
@@ -520,8 +535,11 @@ async function solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress
520
535
  if (impactPercent > maxImpactPercent) {
521
536
  throw new Error(`Price impact too high: ${impactPercent.toFixed(2)}%`);
522
537
  }
523
- // Amount in is within our budget
524
- if (amountIn <= BigInt(srcAmount)) {
538
+ // Amount in is within our budget — accept up to 0.5% over to absorb
539
+ // rounding noise from the bridge's internal pricing (otherwise the loop
540
+ // bounces on quotes that are e.g. 0.1% over, until convergence breaks).
541
+ const budgetWithTolerance = BigInt(srcAmount) * 1005n / 1000n;
542
+ if (amountIn <= budgetWithTolerance) {
525
543
  console.log('[SilentSwap:SolveRelay] Found optimal amount', {
526
544
  usdcOut: amountOut.toString(),
527
545
  amountIn: amountIn.toString(),
@@ -536,7 +554,13 @@ async function solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress
536
554
  .minus(srcAmount)
537
555
  .times(yg_utoken_price)
538
556
  .div(yg_uusdc_price);
539
- const sg_uusdc_target = BigNumber(quote.details.currencyOut.amount)
557
+ // Anchor the next target on the *current target* (what we asked for),
558
+ // not on `currencyOut.amount` (what the bridge's quote estimates we'd
559
+ // get). For some endpoints — notably deBridge single-chain —
560
+ // `amount > requested target` because of a built-in slippage buffer,
561
+ // and using it as the base produces new_target > previous_target on
562
+ // tight iterations, breaking convergence.
563
+ const sg_uusdc_target = BigNumber(targetUsdcOut.toString())
540
564
  .minus(yg_uusdc_over)
541
565
  .toFixed(0);
542
566
  console.log(`[SilentSwap:SolveRelay] Reducing target`, {
@@ -622,8 +646,10 @@ async function solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddr
622
646
  throw new Error(`Price impact too high: ${impactPercent.toFixed(2)}%`);
623
647
  }
624
648
  const amountIn = BigInt(quote.estimation.srcChainTokenIn.amount);
625
- // Amount in is within our budget
626
- if (amountIn <= BigInt(srcAmount)) {
649
+ // Amount in is within our budget — accept up to 0.5% over to absorb
650
+ // rounding noise from deBridge's internal pricing.
651
+ const budgetWithTolerance = BigInt(srcAmount) * 1005n / 1000n;
652
+ if (amountIn <= budgetWithTolerance) {
627
653
  // quote.tx can be undefined when DeBridge returns an estimation-only response
628
654
  // (e.g. unroutable edge cases, takers without capacity for the route, or non-EVM
629
655
  // sources like Solana/Tron where no ERC-20 allowance is needed at all).
@@ -641,7 +667,14 @@ async function solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddr
641
667
  .minus(srcAmount)
642
668
  .times(yg_utoken_price)
643
669
  .div(yg_uusdc_price);
644
- const sg_uusdc_target = BigNumber(quote.estimation.dstChainTokenOut.amount)
670
+ // Anchor on the *requested target* (targetUsdcOut), not the bridge's
671
+ // estimated `amount`. deBridge's single-chain endpoint returns
672
+ // `amount > minAmount` (built-in slippage buffer), which makes the
673
+ // current iteration's `dstChainTokenOut.amount` larger than the
674
+ // requested target. Subtracting a small overshoot from that larger
675
+ // value yields a new target that's still bigger than the previous
676
+ // target, and the convergence guard fires.
677
+ const sg_uusdc_target = BigNumber(targetUsdcOut.toString())
645
678
  .minus(yg_uusdc_over)
646
679
  .toFixed(0);
647
680
  if (BigInt(sg_uusdc_target) >= targetUsdcOut) {
@@ -714,8 +747,10 @@ async function solveDebridgeSingleChainUsdcAmount(chainId, srcToken, srcAmount,
714
747
  throw new Error(`Price impact too high: ${impactPercent.toFixed(2)}%`);
715
748
  }
716
749
  const amountIn = BigInt(quote.estimation.srcChainTokenIn.amount);
717
- // Amount in is within our budget
718
- if (amountIn <= BigInt(srcAmount)) {
750
+ // Amount in is within our budget — accept up to 0.5% over to absorb
751
+ // rounding noise from deBridge's internal pricing.
752
+ const budgetWithTolerance = BigInt(srcAmount) * 1005n / 1000n;
753
+ if (amountIn <= budgetWithTolerance) {
719
754
  // quote.tx can be undefined when DeBridge returns an estimation-only response
720
755
  // (e.g. unroutable edge cases, takers without capacity for the route, or non-EVM
721
756
  // sources like Solana/Tron where no ERC-20 allowance is needed at all).
@@ -733,7 +768,14 @@ async function solveDebridgeSingleChainUsdcAmount(chainId, srcToken, srcAmount,
733
768
  .minus(srcAmount)
734
769
  .times(yg_utoken_price)
735
770
  .div(yg_uusdc_price);
736
- const sg_uusdc_target = BigNumber(quote.estimation.dstChainTokenOut.amount)
771
+ // Anchor on the *requested target* (targetUsdcOut), not the bridge's
772
+ // estimated `amount`. deBridge's single-chain endpoint returns
773
+ // `amount > minAmount` (built-in slippage buffer), which makes the
774
+ // current iteration's `dstChainTokenOut.amount` larger than the
775
+ // requested target. Subtracting a small overshoot from that larger
776
+ // value yields a new target that's still bigger than the previous
777
+ // target, and the convergence guard fires.
778
+ const sg_uusdc_target = BigNumber(targetUsdcOut.toString())
737
779
  .minus(yg_uusdc_over)
738
780
  .toFixed(0);
739
781
  if (BigInt(sg_uusdc_target) >= targetUsdcOut) {
@@ -758,6 +800,12 @@ async function solveDebridgeSingleChainUsdcAmount(chainId, srcToken, srcAmount,
758
800
  */
759
801
  export async function solveOptimalUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, depositCalldata, maxImpactPercent, depositorAddress, evmSignerAddress, // Optional EVM address for deposit calldata (required for non-EVM swaps: Solana, Bitcoin)
760
802
  forceProvider) {
803
+ // Check cache first
804
+ const cacheKey = getQuoteCacheKey(srcChainId, srcToken, srcAmount, forceProvider);
805
+ const cached = quoteCache.get(cacheKey);
806
+ if (cached && Date.now() - cached.timestamp < QUOTE_CACHE_TTL) {
807
+ return cached.result;
808
+ }
761
809
  // Check if this is a non-EVM chain (Solana, Bitcoin, etc.)
762
810
  const isNonEvmChain = isNonEvmRelayChainId(srcChainId);
763
811
  // For non-EVM chains (Solana, Bitcoin), we need an EVM address for deposit calldata
@@ -775,15 +823,33 @@ forceProvider) {
775
823
  const recipientAddress = isNonEvmChain && evmSignerAddress ? evmSignerAddress : userAddress;
776
824
  const useRelay = forceProvider !== 'debridge';
777
825
  const useDebridge = forceProvider !== 'relay';
778
- // Try enabled providers in parallel
779
- const [relayResult, debridgeResult] = await Promise.allSettled([
780
- useRelay
781
- ? solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, calldata, maxImpactPercent, depositorAddress, recipientAddress)
782
- : Promise.resolve(null),
783
- useDebridge
784
- ? solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, calldata, maxImpactPercent, depositorAddress)
785
- : Promise.resolve(null),
786
- ]);
826
+ // Build promise array only for enabled providers to avoid creating unnecessary promises
827
+ const promises = [];
828
+ if (useRelay) {
829
+ promises.push(solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, calldata, maxImpactPercent, depositorAddress, recipientAddress)
830
+ .then(([usdcAmountOut, actualAmountIn, allowanceTarget]) => ({
831
+ usdcAmountOut,
832
+ actualAmountIn,
833
+ provider: 'relay',
834
+ allowanceTarget,
835
+ })));
836
+ }
837
+ else {
838
+ promises.push(Promise.resolve(null));
839
+ }
840
+ if (useDebridge) {
841
+ promises.push(solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, calldata, maxImpactPercent, depositorAddress)
842
+ .then(([usdcAmountOut, actualAmountIn, allowanceTarget]) => ({
843
+ usdcAmountOut,
844
+ actualAmountIn,
845
+ provider: 'debridge',
846
+ allowanceTarget,
847
+ })));
848
+ }
849
+ else {
850
+ promises.push(Promise.resolve(null));
851
+ }
852
+ const [relayResult, debridgeResult] = await Promise.allSettled(promises);
787
853
  // Extract results
788
854
  const relayData = relayResult.status === 'fulfilled' ? relayResult.value : null;
789
855
  const debridgeData = debridgeResult.status === 'fulfilled' ? debridgeResult.value : null;
@@ -807,48 +873,53 @@ forceProvider) {
807
873
  }
808
874
  throw new AggregateError(errors, 'All bridge providers failed');
809
875
  }
876
+ // Helper to cache and return result
877
+ const cacheAndReturn = (result) => {
878
+ quoteCache.set(cacheKey, { result, timestamp: Date.now() });
879
+ return result;
880
+ };
810
881
  // Only one succeeded
811
882
  if (!relayData) {
812
883
  console.info('Using deBridge (relay failed)');
813
- return {
814
- usdcAmountOut: debridgeData[0],
815
- actualAmountIn: debridgeData[1],
884
+ return cacheAndReturn({
885
+ usdcAmountOut: debridgeData.usdcAmountOut,
886
+ actualAmountIn: debridgeData.actualAmountIn,
816
887
  provider: 'debridge',
817
- allowanceTarget: debridgeData[2],
818
- };
888
+ allowanceTarget: debridgeData.allowanceTarget,
889
+ });
819
890
  }
820
891
  if (!debridgeData) {
821
892
  console.info('Using relay.link (deBridge failed)');
822
- return {
823
- usdcAmountOut: relayData[0],
824
- actualAmountIn: relayData[1],
893
+ return cacheAndReturn({
894
+ usdcAmountOut: relayData.usdcAmountOut,
895
+ actualAmountIn: relayData.actualAmountIn,
825
896
  provider: 'relay',
826
- allowanceTarget: relayData[2],
827
- };
897
+ allowanceTarget: relayData.allowanceTarget,
898
+ });
828
899
  }
829
900
  // Compare rates (USDC out / amount in)
830
901
  // Use BigNumber for precision (matching Svelte implementation)
831
902
  // Svelte: yx_rate_relay = BigNumber(xg_uusdc_out_relay).div(xg_amount_in_relay)
832
- const relayRate = BigNumber(relayData[0].toString()).div(relayData[1].toString());
833
- const debridgeRate = BigNumber(debridgeData[0].toString()).div(debridgeData[1].toString());
903
+ const relayRate = BigNumber(relayData.usdcAmountOut.toString()).div(relayData.actualAmountIn.toString());
904
+ const debridgeRate = BigNumber(debridgeData.usdcAmountOut.toString()).div(debridgeData.actualAmountIn.toString());
834
905
  // Relay performs better (matches Svelte: yx_rate_relay.gte(yx_rate_debridge))
835
906
  if (relayRate.gte(debridgeRate)) {
836
- console.info(`Using relay.link: ${relayRate.toString()} >= ${debridgeRate.toString()}`, [relayData[0], relayData[1]], [debridgeData[0], debridgeData[1]]);
837
- return {
838
- usdcAmountOut: relayData[0],
839
- actualAmountIn: relayData[1],
907
+ console.info(`Using relay.link: ${relayRate.toString()} >= ${debridgeRate.toString()}`, [relayData.usdcAmountOut, relayData.actualAmountIn], [debridgeData.usdcAmountOut, debridgeData.actualAmountIn]);
908
+ return cacheAndReturn({
909
+ usdcAmountOut: relayData.usdcAmountOut,
910
+ actualAmountIn: relayData.actualAmountIn,
840
911
  provider: 'relay',
841
912
  allowanceTarget: '',
842
- };
913
+ });
843
914
  }
844
915
  else {
845
916
  // DeBridge performs better
846
- console.info(`Using deBridge: ${debridgeRate.toString()} >= ${relayRate.toString()}`, [debridgeData[0], debridgeData[1]], [relayData[0], relayData[1]]);
847
- return {
848
- usdcAmountOut: debridgeData[0],
849
- actualAmountIn: debridgeData[1],
917
+ console.info(`Using deBridge: ${debridgeRate.toString()} >= ${relayRate.toString()}`, [debridgeData.usdcAmountOut, debridgeData.actualAmountIn], [relayData.usdcAmountOut, relayData.actualAmountIn]);
918
+ return cacheAndReturn({
919
+ usdcAmountOut: debridgeData.usdcAmountOut,
920
+ actualAmountIn: debridgeData.actualAmountIn,
850
921
  provider: 'debridge',
851
- allowanceTarget: debridgeData[2],
852
- };
922
+ allowanceTarget: debridgeData.allowanceTarget,
923
+ });
853
924
  }
854
925
  }
package/dist/chain.js CHANGED
@@ -31,12 +31,10 @@ export async function ensureChain(chainId, walletClient, connector, options) {
31
31
  }
32
32
  console.log('[ensureChain] currentChainId:', currentChainId, 'targetChainId:', chainId, 'needsSwitch:', currentChainId !== chainId);
33
33
  if (currentChainId !== chainId) {
34
- let switchSucceeded = false;
35
34
  try {
36
35
  // Try to switch chain
37
36
  console.log('[ensureChain] attempting switchChain ...', { hasSwitchChain: !!connector.switchChain });
38
37
  await connector.switchChain?.({ chainId });
39
- switchSucceeded = true;
40
38
  console.log('[ensureChain] switchChain succeeded');
41
39
  }
42
40
  catch (switchError) {
@@ -49,16 +47,17 @@ export async function ensureChain(chainId, walletClient, connector, options) {
49
47
  }
50
48
  // Non-required: chain switch failed (e.g. Trust Wallet via WalletConnect
51
49
  // doesn't support programmatic chain switching). Still recreate the
52
- // walletClient from the provider so the WalletConnect transport is fresh
53
- // — TrustWallet silently drops signTypedData when the client's chain scope
54
- // doesn't match its active session chain.
50
+ // walletClient from the provider below so the WalletConnect transport
51
+ // is fresh — TrustWallet silently drops signTypedData when the client's
52
+ // chain scope doesn't match its active session chain.
55
53
  }
56
- // Always recreate walletClient from the provider after a chain change attempt.
57
- // Critical for WalletConnect: the old walletClient's chain scope (e.g. eip155:43114)
58
- // doesn't match the active chain, so signing requests get silently dropped
59
- // by the mobile wallet. This applies both after a successful switch AND a failed
60
- // one the provider's internal state may still have updated even if switchChain threw.
61
- console.log('[ensureChain] recreating walletClient from provider ...', { switchSucceeded });
54
+ // Always rebind the walletClient if its `chain` config doesn't match the target.
55
+ // viem's signTypedData / sendTransaction asserts that walletClient.chain.id matches
56
+ // the wallet's reported eth_chainId if the wallet was already switched to `chainId`
57
+ // (e.g. by an earlier ensureChain call) but the closure's walletClient was created
58
+ // by wagmi with a different chain, signing throws "Provided chainId X must match
59
+ // active chainId Y". Recreating the client here keeps the two in sync.
60
+ console.log('[ensureChain] rebinding walletClient to chain', chainId, '(was', walletClient.chain?.id, ')');
62
61
  const provider = await connector.getProvider();
63
62
  const chain = getChainById(chainId);
64
63
  if (!chain) {
@@ -78,7 +77,7 @@ export async function ensureChain(chainId, walletClient, connector, options) {
78
77
  });
79
78
  return newClient;
80
79
  }
81
- console.log('[ensureChain] already on correct chain, returning existing walletClient');
80
+ console.log('[ensureChain] already on correct chain with matching client, returning existing walletClient');
82
81
  return walletClient;
83
82
  }
84
83
  /**
package/dist/index.d.ts CHANGED
@@ -1,31 +1,40 @@
1
1
  export type { SilentSwapClientConfig, SilentSwapClient, } from './client.js';
2
- export type * from './types/api.js';
2
+ export type { NonceResponse, AuthRequest, AuthResponse, QuoteRequest, QuoteResponse, OrderRequest, DepositParams, OrderResponse, } from './types/api.js';
3
3
  export type { Caip19, SignInMessage } from './types/core.js';
4
4
  export type { EvmSigner } from './types/sdk.js';
5
- export * from './order.js';
6
- export * from './caip19.js';
5
+ export type { FacilitatorPublicKey, Eip712Document, Eip3009TypedData, AuthorizationInstruction, AuthorizationReply, FacilitatorInstruction, FacilitatorReply, OrderOutputArg, OrderMetadata, Quote, Order, } from './order.js';
6
+ export { DeliveryMethod, PrivacySetting, FacilitatorKeyType, PublicKeyArgGroups, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION, EIP712_DOMAIN_ORDER_DEFAULT, EIP712_DOMAIN_WALLET_GENERATION, quoteResponseToEip712Document, } from './order.js';
7
+ export type { Caip19Parts, ParsedCaip19, ParsedEvmCaip19, ParsedSolanaCaip19, ParsedTronCaip19, } from './caip19.js';
8
+ export { CAIP19_REGEX, EVM_CAIP19_REGEX, SOLANA_CAIP19_REGEX, TRON_CAIP19_NATIVE_REGEX, TRON_CAIP19_TOKEN_REGEX, Caip19Namespace, parseCaip19, parseEvmCaip19, parseSolanaCaip19, parseTronCaip19, getChainNamespace, getChainId, getEvmChainId, getAssetNamespace, getAssetReference, getEvmTokenAddress, getCaip2FromCaip19, isNativeToken, isEvmAsset, isSolanaAsset, isTronAsset, BIP122_BITCOIN_MAINNET_CHAIN_ID, isBitcoinAsset, isBitcoinMainnetAsset, isEvmNativeToken, isErc20Token, isSolanaNativeToken, isSplToken, caip19FromParts, caip19FungibleEvmToken, caip19NativeEvmToken, caip19SplToken, caip19NativeSolanaToken, } from './caip19.js';
7
9
  export { createSilentSwapClient, } from './client.js';
8
- export * from './constants.js';
9
- export * from './gateway-abi.js';
10
+ export type { CalculationDirection, } from './constants.js';
11
+ export { EVM_PHONY_ADDRESS, EVM_NATIVE_ADDRESS, DEAD_ADDRESS, S0X_ADDR_EVM_ZERO, UINT256_MAX, MAINNET_GATEWAY_ADDRESS, MAINNET_GATEWAY_PUBLIC_KEY, ENVIRONMENT, ENVIRONMENT_CONFIGS, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE, NI_CHAIN_ID_AVALANCHE, XT_TTL_SESSION_CACHE, X_MINIMUM_INPUT_USD, X_MAX_IMPACT_PERCENT, COIN_TYPES, SB58_CHAIN_ID_SOLANA_MAINNET, SB58_ADDR_SOL_PROGRAM_SYSTEM, SB58_ADDR_SOL_RELAY_LINK_RECIPIENT, SB58_ADDR_SOL_DEAD, SBTC_ADDR_BITCOIN_NATIVE, SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT, S0X_ADDR_TRON_NATIVE, SB58_ADDR_TRON_DEAD, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_TRON, N_RELAY_CHAIN_ID_SUI, N_DEBRIDGE_CHAIN_ID_SOLANA, N_DEBRIDGE_CHAIN_ID_TRON, S0X_ADDR_EVM_RELAY_LINK_DEAD, P_URL_API_RPC_SOLANA, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from './constants.js';
12
+ export { GATEWAY_ABI, } from './gateway-abi.js';
10
13
  export { createHdFacilitatorGroupFromEntropy, exportSecretMnemonicFromEntropy, type HdFacilitatorGroup, } from './hd-facilitator-group.js';
11
14
  export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
12
15
  export { createViemSigner, parseTransactionRequestForViem, } from './signer-adapters/viem.js';
13
- export * from './bridge.js';
14
- export * from './quote-utils.js';
15
- export * from './transaction-utils.js';
16
- export * from './wallet.js';
17
- export * from './storage.js';
18
- export * from './chain.js';
19
- export * from './chains.js';
20
- export * from './rpc.js';
21
- export * from './assets.js';
22
- export * from './encoding.js';
23
- export * from './refund.js';
16
+ export type { BridgeProvider, BridgeQuote, SolanaInstruction, BridgeTransaction, BridgeStatus, BridgeQuoteParams, RelayQuoteParams, RelayQuoteResponse, DeBridgeOrderParams, DeBridgeOrderResponse, SolveUsdcResult, } from './bridge.js';
17
+ export { getRelayOriginAsset, executeRelayBridge, executeDebridgeBridge, getRelayStatus, getDebridgeStatus, fetchRelayQuote, fetchDebridgeOrder, solveOptimalUsdcAmount, } from './bridge.js';
18
+ export type { EstimateSample, Estimate, QuoteMetrics, BridgeQuoteResult, ForceBridgeProvider, } from './quote-utils.js';
19
+ export { calculateRelayMetrics, calculateDebridgeMetrics, selectBestQuote, interpolateSamples, getBridgeQuote, convertQuoteResultToQuote, } from './quote-utils.js';
20
+ export type { SolanaTransactionExecutor, BitcoinTransactionExecutor, TronTransactionExecutor, UniversalTransactionExecutor, } from './transaction-utils.js';
21
+ export { createTransactionExecutor, createChainSwitcher, executeBridgeTransaction, getBridgeStatus, } from './transaction-utils.js';
22
+ export { queryDepositCount, createPhonyDepositCalldata, } from './wallet.js';
23
+ export { STORAGE_KEY_AUTH_PREFIX, STORAGE_KEY_WALLET_PREFIX, getAuthStorageKey, getWalletStorageKey, loadCachedAuth, saveAuth, clearAuth, saveWalletData, loadWalletData, clearWalletData, } from './storage.js';
24
+ export { ensureChain, pingWalletConnectSession, clearStaleWalletConnectSessions, createPublicClientWithRpc, waitForTransactionConfirmation, executeTransaction, } from './chain.js';
25
+ export { SOLANA_CHAIN_ID, BITCOIN_CHAIN_ID, TRON_CHAIN_ID, A_VIEM_CHAINS, getChainById, } from './chains.js';
26
+ export { H_RPCS, } from './rpc.js';
27
+ export type { AssetInfo, ChainInfo, AssetsData, } from './assets.js';
28
+ export { loadAssetsData, getAllAssets, getAllChains, getAllAssetsArray, getCommonAssets, COMMON_ASSETS, CHAIN_NAMES, getAssetByCaip19, getChainByCaip2, getAssetsByChain, getChainName, searchAssets, } from './assets.js';
29
+ export { hexToBytes, bytesToBase58, hexToBase58, base93ToBytes, bytesToBase93, } from './encoding.js';
30
+ export type { GatewayOrderStatus, RefundEligibility, } from './refund.js';
31
+ export { DepositStatus, orderIdToBytes32, queryOrderStatus, checkRefundEligibility, executeRefund, checkRecoveryEligibility, } from './refund.js';
24
32
  export { trackOrderViaWebSocket, getOrderTrackingWebSocketUrl, type TrackOrderOptions, type OrderStatusUpdate, } from './order-tracking.js';
25
33
  export type { NaiveBase58, NaiveBase93, NaiveHexLower, NaiveHexUpper } from './belt-utils.js';
26
34
  export { bytes_to_base58, base58_to_bytes, bytes_to_base93, base93_to_bytes, bytes_to_hex, hex_to_bytes } from './belt-utils.js';
27
- export * from './address.js';
28
- export * from './asset-utils.js';
29
- export * from './solana-utils.js';
30
- export * from './errors.js';
35
+ export type { ContactSource, Contact, Caip10, } from './address.js';
36
+ export { isValidEvmAddress, isValidSolanaAddress, isValidBitcoinAddress, isValidTronAddress, validateAddress, normalizeAddress, isValidEnsName, formatAddress, formatAddressByType, getAvatarColor, getAvatarInitials, createCaip10, parseCaip10, getAddressFromCaip10, evmAddressToCaip10, solanaAddressToCaip10, bitcoinAddressToCaip10, addressToCaip10, isContactCompatibleWithAsset, filterContacts, } from './address.js';
37
+ export { parseCaip19Legacy, getChainNamespaceFromAsset, getChainIdFromAsset, getAssetNamespaceFromAsset, getAssetId, getCaip2, getTokenAddress, isBitcoin, isEvm, isSolana, isCosmos, isSui, isTron, isNativeTokenFromAsset, isEvmNative, isEvmErc20, isSolanaNative, isSolanaToken, isCosmosNative, isCosmosIbc, getTokenChainId, getTokenChainIdString, extractChainIdsFromAssets, extractChainIdFromAsset, getTokenChainInfo, getTokenChainName, switchChainNamespace, } from './asset-utils.js';
38
+ export { getSolanaRpcUrl, } from './solana-utils.js';
39
+ export { SilentSwapError, ApiError, NetworkError, AuthenticationError, QuoteError, OrderError, ValidationError, ConfigurationError, WalletError, TransactionError, createErrorFromResponse, } from './errors.js';
31
40
  export { executeSolanaSwap, type SwapEnvironment, type OutputStage, type OrderStatus, type SwapStatusUpdate, type SwapResult, type EvmAccount, type SolanaAccount, type SwapAccounts, type SolanaSwapConfig, } from './swap-executor.js';
package/dist/index.js CHANGED
@@ -1,31 +1,37 @@
1
- export * from './order.js';
2
- export * from './caip19.js';
1
+ export { DeliveryMethod, PrivacySetting, FacilitatorKeyType, PublicKeyArgGroups, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION, EIP712_DOMAIN_ORDER_DEFAULT, EIP712_DOMAIN_WALLET_GENERATION, quoteResponseToEip712Document, } from './order.js';
2
+ export { CAIP19_REGEX, EVM_CAIP19_REGEX, SOLANA_CAIP19_REGEX, TRON_CAIP19_NATIVE_REGEX, TRON_CAIP19_TOKEN_REGEX, Caip19Namespace, parseCaip19, parseEvmCaip19, parseSolanaCaip19, parseTronCaip19, getChainNamespace, getChainId, getEvmChainId, getAssetNamespace, getAssetReference, getEvmTokenAddress, getCaip2FromCaip19, isNativeToken, isEvmAsset, isSolanaAsset, isTronAsset, BIP122_BITCOIN_MAINNET_CHAIN_ID, isBitcoinAsset, isBitcoinMainnetAsset, isEvmNativeToken, isErc20Token, isSolanaNativeToken, isSplToken, caip19FromParts, caip19FungibleEvmToken, caip19NativeEvmToken, caip19SplToken, caip19NativeSolanaToken, } from './caip19.js';
3
3
  export { createSilentSwapClient, } from './client.js';
4
- export * from './constants.js';
5
- export * from './gateway-abi.js';
4
+ export { EVM_PHONY_ADDRESS, EVM_NATIVE_ADDRESS, DEAD_ADDRESS, S0X_ADDR_EVM_ZERO, UINT256_MAX, MAINNET_GATEWAY_ADDRESS, MAINNET_GATEWAY_PUBLIC_KEY, ENVIRONMENT, ENVIRONMENT_CONFIGS, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE, NI_CHAIN_ID_AVALANCHE, XT_TTL_SESSION_CACHE, X_MINIMUM_INPUT_USD, X_MAX_IMPACT_PERCENT, COIN_TYPES, SB58_CHAIN_ID_SOLANA_MAINNET, SB58_ADDR_SOL_PROGRAM_SYSTEM, SB58_ADDR_SOL_RELAY_LINK_RECIPIENT, SB58_ADDR_SOL_DEAD, SBTC_ADDR_BITCOIN_NATIVE, SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT, S0X_ADDR_TRON_NATIVE, SB58_ADDR_TRON_DEAD, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_TRON, N_RELAY_CHAIN_ID_SUI, N_DEBRIDGE_CHAIN_ID_SOLANA, N_DEBRIDGE_CHAIN_ID_TRON, S0X_ADDR_EVM_RELAY_LINK_DEAD, P_URL_API_RPC_SOLANA, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from './constants.js';
5
+ // gateway-abi
6
+ export { GATEWAY_ABI, } from './gateway-abi.js';
6
7
  export { createHdFacilitatorGroupFromEntropy, exportSecretMnemonicFromEntropy, } from './hd-facilitator-group.js';
7
8
  export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
8
9
  export { createViemSigner, parseTransactionRequestForViem, } from './signer-adapters/viem.js';
9
- export * from './bridge.js';
10
- export * from './quote-utils.js';
11
- export * from './transaction-utils.js';
12
- export * from './wallet.js';
13
- export * from './storage.js';
14
- export * from './chain.js';
15
- export * from './chains.js';
16
- export * from './rpc.js';
17
- export * from './assets.js';
18
- export * from './encoding.js';
19
- export * from './refund.js';
10
+ export { getRelayOriginAsset, executeRelayBridge, executeDebridgeBridge, getRelayStatus, getDebridgeStatus, fetchRelayQuote, fetchDebridgeOrder, solveOptimalUsdcAmount, } from './bridge.js';
11
+ export { calculateRelayMetrics, calculateDebridgeMetrics, selectBestQuote, interpolateSamples, getBridgeQuote, convertQuoteResultToQuote, } from './quote-utils.js';
12
+ export { createTransactionExecutor, createChainSwitcher, executeBridgeTransaction, getBridgeStatus, } from './transaction-utils.js';
13
+ // wallet
14
+ export { queryDepositCount, createPhonyDepositCalldata, } from './wallet.js';
15
+ // storage
16
+ export { STORAGE_KEY_AUTH_PREFIX, STORAGE_KEY_WALLET_PREFIX, getAuthStorageKey, getWalletStorageKey, loadCachedAuth, saveAuth, clearAuth, saveWalletData, loadWalletData, clearWalletData, } from './storage.js';
17
+ // chain
18
+ export { ensureChain, pingWalletConnectSession, clearStaleWalletConnectSessions, createPublicClientWithRpc, waitForTransactionConfirmation, executeTransaction, } from './chain.js';
19
+ // chains
20
+ export { SOLANA_CHAIN_ID, BITCOIN_CHAIN_ID, TRON_CHAIN_ID, A_VIEM_CHAINS, getChainById, } from './chains.js';
21
+ // rpc
22
+ export { H_RPCS, } from './rpc.js';
23
+ export { loadAssetsData, getAllAssets, getAllChains, getAllAssetsArray, getCommonAssets, COMMON_ASSETS, CHAIN_NAMES, getAssetByCaip19, getChainByCaip2, getAssetsByChain, getChainName, searchAssets, } from './assets.js';
24
+ // encoding
25
+ export { hexToBytes, bytesToBase58, hexToBase58, base93ToBytes, bytesToBase93, } from './encoding.js';
26
+ export { DepositStatus, orderIdToBytes32, queryOrderStatus, checkRefundEligibility, executeRefund, checkRecoveryEligibility, } from './refund.js';
20
27
  export { trackOrderViaWebSocket, getOrderTrackingWebSocketUrl, } from './order-tracking.js';
21
28
  export { bytes_to_base58, base58_to_bytes, bytes_to_base93, base93_to_bytes, bytes_to_hex, hex_to_bytes } from './belt-utils.js';
22
- export * from './address.js';
23
- // Export asset-utils functions (AssetInfo-based wrappers)
24
- // Note: parseCaip19, getChainNamespace, getChainId, getAssetNamespace, and isNativeToken
25
- // have the same names as caip19.js but take AssetInfo instead of string.
26
- // TypeScript will use the parameter type to distinguish them at call sites.
27
- export * from './asset-utils.js';
28
- export * from './solana-utils.js';
29
- export * from './errors.js';
29
+ export { isValidEvmAddress, isValidSolanaAddress, isValidBitcoinAddress, isValidTronAddress, validateAddress, normalizeAddress, isValidEnsName, formatAddress, formatAddressByType, getAvatarColor, getAvatarInitials, createCaip10, parseCaip10, getAddressFromCaip10, evmAddressToCaip10, solanaAddressToCaip10, bitcoinAddressToCaip10, addressToCaip10, isContactCompatibleWithAsset, filterContacts, } from './address.js';
30
+ // asset-utils
31
+ export { parseCaip19Legacy, getChainNamespaceFromAsset, getChainIdFromAsset, getAssetNamespaceFromAsset, getAssetId, getCaip2, getTokenAddress, isBitcoin, isEvm, isSolana, isCosmos, isSui, isTron, isNativeTokenFromAsset, isEvmNative, isEvmErc20, isSolanaNative, isSolanaToken, isCosmosNative, isCosmosIbc, getTokenChainId, getTokenChainIdString, extractChainIdsFromAssets, extractChainIdFromAsset, getTokenChainInfo, getTokenChainName, switchChainNamespace, } from './asset-utils.js';
32
+ // solana-utils
33
+ export { getSolanaRpcUrl, } from './solana-utils.js';
34
+ // errors
35
+ export { SilentSwapError, ApiError, NetworkError, AuthenticationError, QuoteError, OrderError, ValidationError, ConfigurationError, WalletError, TransactionError, createErrorFromResponse, } from './errors.js';
30
36
  // Swap executor for Node.js integrators
31
37
  export { executeSolanaSwap, } from './swap-executor.js';
package/dist/order.d.ts CHANGED
@@ -276,5 +276,10 @@ export declare const EIP712_DOMAIN_ORDER_DEFAULT: {
276
276
  readonly version: "1";
277
277
  readonly chainId: 1;
278
278
  };
279
+ export declare const EIP712_DOMAIN_WALLET_GENERATION: {
280
+ readonly name: "SilentSwap v2";
281
+ readonly version: "1";
282
+ readonly chainId: 43114;
283
+ };
279
284
  export declare function quoteResponseToEip712Document(quoteResponse: QuoteResponse): TypedDataDocument<typeof EIP712_DOMAIN_ORDER_DEFAULT>;
280
285
  export {};
package/dist/order.js CHANGED
@@ -94,11 +94,25 @@ export const EIP712_TYPES_WALLET_GENERATION = {
94
94
  { name: 'token', type: 'string' },
95
95
  ],
96
96
  };
97
+ // Orders must be signed with chainId === 1 (Ethereum mainnet) — the backend
98
+ // rejects any other chainId with "eip712Domain value is invalid or not supported.
99
+ // expected mainnet chain ID 1". Wallet-generation typed data uses a different
100
+ // domain (EIP712_DOMAIN_WALLET_GENERATION below) and is not subject to that
101
+ // constraint.
97
102
  export const EIP712_DOMAIN_ORDER_DEFAULT = {
98
103
  name: 'SilentSwap v2',
99
104
  version: '1',
100
105
  chainId: 1,
101
106
  };
107
+ // Wallet-generation typed data is signed locally to derive entropy — the chainId
108
+ // only matters for the wallet's cross-chain replay-protection check at sign time.
109
+ // Pinned to Avalanche (43114) so the user doesn't have to leave their working
110
+ // chain just to derive the wallet.
111
+ export const EIP712_DOMAIN_WALLET_GENERATION = {
112
+ name: 'SilentSwap v2',
113
+ version: '1',
114
+ chainId: 43114,
115
+ };
102
116
  export function quoteResponseToEip712Document(quoteResponse) {
103
117
  return {
104
118
  domain: EIP712_DOMAIN_ORDER_DEFAULT,
package/dist/sdk.d.ts CHANGED
@@ -156,7 +156,7 @@ export declare function createEip712DocForWalletGeneration(scope: string, token:
156
156
  domain: {
157
157
  readonly name: "SilentSwap v2";
158
158
  readonly version: "1";
159
- readonly chainId: 1;
159
+ readonly chainId: 43114;
160
160
  };
161
161
  primaryType: "WalletGeneration";
162
162
  message: {
package/dist/sdk.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createSiweMessage } from 'viem/siwe';
2
- import { EIP712_DOMAIN_ORDER_DEFAULT, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION } from './order.js';
2
+ import { EIP712_DOMAIN_ORDER_DEFAULT, EIP712_DOMAIN_WALLET_GENERATION, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION } from './order.js';
3
3
  /**
4
4
  * Creates a SIWE message for authentication with SilentSwap
5
5
  * @param user - user's EVM address
@@ -49,7 +49,7 @@ export function createEip712DocForOrder(quote) {
49
49
  export function createEip712DocForWalletGeneration(scope, token) {
50
50
  return {
51
51
  types: EIP712_TYPES_WALLET_GENERATION,
52
- domain: EIP712_DOMAIN_ORDER_DEFAULT,
52
+ domain: EIP712_DOMAIN_WALLET_GENERATION,
53
53
  primaryType: 'WalletGeneration',
54
54
  message: {
55
55
  description: 'Securely create a temporary, anonymous wallet for SilentSwap use only.',
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@silentswap/sdk",
3
3
  "type": "module",
4
- "version": "0.1.63",
4
+ "version": "0.1.65",
5
5
  "license": "MIT",
6
+ "sideEffects": false,
6
7
  "main": "dist/index.js",
7
8
  "files": [
8
9
  "dist",