@pear-protocol/symmio-client 0.3.27 → 0.3.29

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.
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { createContext, useContext, useMemo, useCallback, useState, useEffect, useRef } from 'react';
3
- import { createSymmSDK, TpslStatus, isAuthExpiredError, isNetworkError, isInsufficientMarginError, isRateLimitedError, isTimeoutError } from '@pear-protocol/symm-core';
3
+ import { createSymmSDK, TpslStatus, HedgerClient, isAuthExpiredError, isNetworkError, isInsufficientMarginError, isRateLimitedError, isTimeoutError, formatChannel } from '@pear-protocol/symm-core';
4
4
  import { create } from 'zustand';
5
5
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
6
6
  import { jsx } from 'react/jsx-runtime';
@@ -697,7 +697,7 @@ function useSymmWs(params = {}) {
697
697
  const isConnected = useSymmWsStore((state) => state.isConnected);
698
698
  const setConnected = useSymmWsStore((state) => state.setConnected);
699
699
  const symmCoreClient = params.symmCoreClient ?? ctx?.symmCoreClient ?? null;
700
- const accountAddress = params.accountAddress ?? ctx?.address;
700
+ const accountAddress = params.accountAddress ?? ctx?.accountAddress;
701
701
  const chainId = params.chainId ?? ctx?.chainId ?? 42161;
702
702
  useEffect(() => {
703
703
  if (!symmCoreClient || !accountAddress) {
@@ -707,14 +707,61 @@ function useSymmWs(params = {}) {
707
707
  const ws = symmCoreClient.ws;
708
708
  const addr = accountAddress;
709
709
  let cancelled = false;
710
+ const subscribedChannelKeys = /* @__PURE__ */ new Set();
710
711
  addWsOwner(ws);
711
- const removeOnConnect = ws.onConnect(() => setConnected(true));
712
- const removeOnDisconnect = ws.onDisconnect(() => setConnected(false));
713
712
  const subscriptions = [];
714
713
  const addSubscription = (channel, handler) => {
715
- ws.subscribe(channel, addr, chainId, handler);
716
714
  subscriptions.push({ channel, handler });
717
715
  };
716
+ const sendWsMessage = (message) => {
717
+ if (!ws.isConnected()) return;
718
+ ws.ws?.send(JSON.stringify(message));
719
+ };
720
+ const getHandlers = (channelKey) => {
721
+ const internals = ws;
722
+ if (!internals.subscriptions) {
723
+ internals.subscriptions = /* @__PURE__ */ new Map();
724
+ }
725
+ let handlers = internals.subscriptions.get(channelKey);
726
+ if (!handlers) {
727
+ handlers = /* @__PURE__ */ new Set();
728
+ internals.subscriptions.set(channelKey, handlers);
729
+ }
730
+ return handlers;
731
+ };
732
+ const subscribeAll = () => {
733
+ subscriptions.forEach(({ channel, handler }) => {
734
+ const channelKey = formatChannel(channel, addr, chainId);
735
+ getHandlers(channelKey).add(handler);
736
+ if (!subscribedChannelKeys.has(channelKey)) {
737
+ sendWsMessage({ type: "subscribe", channel: channelKey });
738
+ subscribedChannelKeys.add(channelKey);
739
+ }
740
+ });
741
+ };
742
+ const unsubscribeAll = (sendUnsubscribe) => {
743
+ subscriptions.forEach(({ channel, handler }) => {
744
+ const channelKey = formatChannel(channel, addr, chainId);
745
+ const internals = ws;
746
+ const handlers = internals.subscriptions?.get(channelKey);
747
+ handlers?.delete(handler);
748
+ if (handlers?.size === 0) {
749
+ internals.subscriptions?.delete(channelKey);
750
+ }
751
+ if (sendUnsubscribe && subscribedChannelKeys.has(channelKey)) {
752
+ sendWsMessage({ type: "unsubscribe", channel: channelKey });
753
+ }
754
+ subscribedChannelKeys.delete(channelKey);
755
+ });
756
+ };
757
+ const removeOnConnect = ws.onConnect(() => {
758
+ setConnected(true);
759
+ subscribeAll();
760
+ });
761
+ const removeOnDisconnect = ws.onDisconnect(() => {
762
+ unsubscribeAll(false);
763
+ setConnected(false);
764
+ });
718
765
  addSubscription("positions", () => {
719
766
  queryClient.invalidateQueries({ queryKey: symmKeys.positionsRoot });
720
767
  });
@@ -756,10 +803,11 @@ function useSymmWs(params = {}) {
756
803
  queryClient.invalidateQueries({ queryKey: symmKeys.positionsRoot });
757
804
  queryClient.invalidateQueries({ queryKey: symmKeys.portfolioRoot });
758
805
  });
759
- void connectShared(ws).then(() => {
806
+ connectShared(ws).then(() => {
760
807
  if (cancelled) return;
761
808
  if (ws.isConnected()) {
762
809
  setConnected(true);
810
+ subscribeAll();
763
811
  }
764
812
  }).catch(() => {
765
813
  if (cancelled) return;
@@ -769,15 +817,13 @@ function useSymmWs(params = {}) {
769
817
  cancelled = true;
770
818
  removeOnConnect();
771
819
  removeOnDisconnect();
772
- subscriptions.forEach(({ channel, handler }) => {
773
- ws.unsubscribe(channel, addr, chainId, handler);
774
- });
820
+ unsubscribeAll(true);
775
821
  if (removeWsOwner(ws) === 0) {
776
822
  ws.disconnect();
777
823
  setConnected(false);
778
824
  }
779
825
  };
780
- }, [symmCoreClient, accountAddress, chainId, queryClient, setConnected]);
826
+ }, [symmCoreClient, accountAddress, chainId]);
781
827
  return { isConnected };
782
828
  }
783
829
  function trimTrailingSlashes(value) {
@@ -786,6 +832,7 @@ function trimTrailingSlashes(value) {
786
832
  function SymmProvider({
787
833
  chainId = 42161,
788
834
  address,
835
+ accountAddress,
789
836
  walletClient,
790
837
  symmCoreConfig = {
791
838
  apiUrl: "https://nginx-server-staging.up.railway.app",
@@ -814,10 +861,11 @@ function SymmProvider({
814
861
  symmCoreClient,
815
862
  chainId,
816
863
  address,
864
+ accountAddress,
817
865
  walletClient,
818
866
  symmioConfig
819
867
  }),
820
- [symmCoreClient, chainId, address, walletClient, symmioConfig]
868
+ [symmCoreClient, chainId, address, accountAddress, walletClient, symmioConfig]
821
869
  );
822
870
  useBinanceWs({
823
871
  symmCoreClient,
@@ -825,7 +873,7 @@ function SymmProvider({
825
873
  });
826
874
  useSymmWs({
827
875
  symmCoreClient,
828
- accountAddress: address,
876
+ accountAddress,
829
877
  chainId
830
878
  });
831
879
  return /* @__PURE__ */ jsx(SymmContext.Provider, { value, children });
@@ -27106,6 +27154,24 @@ function useSymmBalances(params) {
27106
27154
  enabled: internalEnabled && (params.query?.enabled ?? true)
27107
27155
  });
27108
27156
  }
27157
+ function normalizeSideWeights(legs) {
27158
+ if (!legs?.length) return legs;
27159
+ const allWeighted = legs.every(
27160
+ (leg) => typeof leg.weight === "number" && Number.isFinite(leg.weight) && leg.weight > 0
27161
+ );
27162
+ if (!allWeighted) return legs;
27163
+ const total = legs.reduce((sum, leg) => sum + (leg.weight ?? 0), 0);
27164
+ if (total <= 0) return legs;
27165
+ if (Math.abs(total - 1) < 1e-9) return legs;
27166
+ return legs.map((leg) => ({ ...leg, weight: (leg.weight ?? 0) / total }));
27167
+ }
27168
+ function normalizeBasketWeights(request) {
27169
+ return {
27170
+ ...request,
27171
+ longPositions: normalizeSideWeights(request.longPositions),
27172
+ shortPositions: normalizeSideWeights(request.shortPositions)
27173
+ };
27174
+ }
27109
27175
  function useSymmOpenBasketMutation(options) {
27110
27176
  const { symmCoreClient } = useSymmContext();
27111
27177
  const queryClient = useQueryClient();
@@ -27126,10 +27192,12 @@ function useSymmOpenBasketMutation(options) {
27126
27192
  if (!authToken) {
27127
27193
  throw new Error("auth token is required to open a position");
27128
27194
  }
27129
- return symmCoreClient.positions.openBasket({
27130
- ...request,
27131
- authToken
27132
- });
27195
+ return symmCoreClient.positions.openBasket(
27196
+ normalizeBasketWeights({
27197
+ ...request,
27198
+ authToken
27199
+ })
27200
+ );
27133
27201
  }
27134
27202
  });
27135
27203
  }
@@ -27601,18 +27669,14 @@ function useSymmHedgerMarketBySymbol(params) {
27601
27669
  });
27602
27670
  }
27603
27671
  function useSymmLockedParams(params) {
27604
- const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
27672
+ const { chainId: ctxChainId } = useSymmContext();
27605
27673
  const { marketName, leverage } = params;
27606
27674
  const chainId = params.chainId ?? ctxChainId;
27607
- const internalEnabled = !!symmCoreClient && !!marketName && leverage != null;
27675
+ const internalEnabled = !!marketName && leverage != null && typeof chainId === "number";
27608
27676
  return useQuery({
27609
27677
  ...params.query,
27610
27678
  queryKey: symmKeys.lockedParams(marketName, leverage, chainId),
27611
- queryFn: () => symmCoreClient.markets.getLockedParams({
27612
- marketName,
27613
- leverage,
27614
- chainId
27615
- }),
27679
+ queryFn: () => HedgerClient.getLockedParams(chainId, marketName, leverage),
27616
27680
  enabled: internalEnabled && (params.query?.enabled ?? true)
27617
27681
  });
27618
27682
  }