@sundaeswap/wallet-lite 0.0.25 → 0.0.27

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.
Files changed (46) hide show
  1. package/dist/cjs/classes/WalletObserver.class.js +11 -1
  2. package/dist/cjs/classes/WalletObserver.class.js.map +1 -1
  3. package/dist/cjs/react-components/WalletObserverProvider/WalletObserverProvider.js +13 -20
  4. package/dist/cjs/react-components/WalletObserverProvider/WalletObserverProvider.js.map +1 -1
  5. package/dist/cjs/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.js +4 -8
  6. package/dist/cjs/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.js.map +1 -1
  7. package/dist/cjs/react-components/WalletObserverProvider/hooks/useWalletObserverState.js +95 -60
  8. package/dist/cjs/react-components/WalletObserverProvider/hooks/useWalletObserverState.js.map +1 -1
  9. package/dist/cjs/react-components/contexts/observer/types.js.map +1 -1
  10. package/dist/cjs/react-components/hooks/useWalletHandles.js +67 -52
  11. package/dist/cjs/react-components/hooks/useWalletHandles.js.map +1 -1
  12. package/dist/cjs/react-components/hooks/useWalletObserver.js +6 -3
  13. package/dist/cjs/react-components/hooks/useWalletObserver.js.map +1 -1
  14. package/dist/esm/classes/WalletObserver.class.js +9 -1
  15. package/dist/esm/classes/WalletObserver.class.js.map +1 -1
  16. package/dist/esm/react-components/WalletObserverProvider/WalletObserverProvider.js +7 -11
  17. package/dist/esm/react-components/WalletObserverProvider/WalletObserverProvider.js.map +1 -1
  18. package/dist/esm/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.js +4 -8
  19. package/dist/esm/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.js.map +1 -1
  20. package/dist/esm/react-components/WalletObserverProvider/hooks/useWalletObserverState.js +57 -40
  21. package/dist/esm/react-components/WalletObserverProvider/hooks/useWalletObserverState.js.map +1 -1
  22. package/dist/esm/react-components/contexts/observer/types.js.map +1 -1
  23. package/dist/esm/react-components/hooks/useWalletHandles.js +31 -24
  24. package/dist/esm/react-components/hooks/useWalletHandles.js.map +1 -1
  25. package/dist/esm/react-components/hooks/useWalletObserver.js +6 -3
  26. package/dist/esm/react-components/hooks/useWalletObserver.js.map +1 -1
  27. package/dist/types/classes/WalletObserver.class.d.ts +6 -0
  28. package/dist/types/classes/WalletObserver.class.d.ts.map +1 -1
  29. package/dist/types/react-components/WalletObserverProvider/WalletObserverProvider.d.ts.map +1 -1
  30. package/dist/types/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.d.ts +2 -1
  31. package/dist/types/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.d.ts.map +1 -1
  32. package/dist/types/react-components/WalletObserverProvider/hooks/useWalletObserverState.d.ts +4 -0
  33. package/dist/types/react-components/WalletObserverProvider/hooks/useWalletObserverState.d.ts.map +1 -1
  34. package/dist/types/react-components/contexts/observer/types.d.ts +3 -0
  35. package/dist/types/react-components/contexts/observer/types.d.ts.map +1 -1
  36. package/dist/types/react-components/hooks/useWalletHandles.d.ts.map +1 -1
  37. package/dist/types/react-components/hooks/useWalletObserver.d.ts.map +1 -1
  38. package/dist/types/tsconfig.build.tsbuildinfo +1 -1
  39. package/package.json +1 -1
  40. package/src/classes/WalletObserver.class.ts +9 -1
  41. package/src/react-components/WalletObserverProvider/WalletObserverProvider.tsx +6 -9
  42. package/src/react-components/WalletObserverProvider/hooks/effects/useProviderEventListeners.ts +5 -20
  43. package/src/react-components/WalletObserverProvider/hooks/useWalletObserverState.ts +89 -66
  44. package/src/react-components/contexts/observer/types.ts +3 -0
  45. package/src/react-components/hooks/useWalletHandles.ts +69 -62
  46. package/src/react-components/hooks/useWalletObserver.ts +7 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sundaeswap/wallet-lite",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -210,6 +210,15 @@ export class WalletObserver<
210
210
  return this._performingSync;
211
211
  }
212
212
 
213
+ /**
214
+ * Helper method to check if the instance has an active connection.
215
+ *
216
+ * @returns {boolean}
217
+ */
218
+ hasActiveConnection(): boolean {
219
+ return Boolean(this._activeWallet && this.api);
220
+ }
221
+
213
222
  /**
214
223
  * Synchronizes the API with the wallet. This is useful if the account has changed,
215
224
  * but the underlying intent has not.
@@ -380,7 +389,6 @@ export class WalletObserver<
380
389
  disconnect = (): void => {
381
390
  this._activeWallet = undefined;
382
391
  this.api = undefined;
383
- this._cachedMetadata = new Map();
384
392
  window.localStorage.removeItem(WalletObserver.PERSISTENCE_CACHE_KEY);
385
393
  this.dispatch(EWalletObserverEvents.DISCONNECT);
386
394
  };
@@ -22,19 +22,17 @@ const WalletObserverProvider: FC<
22
22
  PropsWithChildren<IWalletObserverProviderProps>
23
23
  > = ({ children, options }) => {
24
24
  const observerRef = useProviderWalletObserverRef(options?.observerOptions);
25
- const { syncWallet, ...reactiveState } = useWalletObserverState(
26
- observerRef.current
27
- );
25
+ const state = useWalletObserverState(observerRef.current);
28
26
 
29
- useProviderEventListeners(observerRef.current, syncWallet);
27
+ useProviderEventListeners(observerRef.current, state);
30
28
  useProviderRefreshInterval(
31
29
  observerRef.current,
32
- syncWallet,
30
+ state.syncWallet,
33
31
  options?.refreshInterval
34
32
  );
35
33
 
36
34
  const derivedState = useDerivedState(observerRef.current, {
37
- usedAddresses: reactiveState.usedAddresses,
35
+ usedAddresses: state.usedAddresses,
38
36
  });
39
37
 
40
38
  // Memoize the context value
@@ -43,13 +41,12 @@ const WalletObserverProvider: FC<
43
41
  observerRef: observerRef,
44
42
  refreshInterval: options?.refreshInterval || 30000,
45
43
  state: {
46
- ...reactiveState,
44
+ ...state,
47
45
  ...derivedState,
48
46
  observer: observerRef.current,
49
- syncWallet,
50
47
  },
51
48
  }),
52
- [options, syncWallet, reactiveState, derivedState]
49
+ [options, state, derivedState]
53
50
  );
54
51
 
55
52
  return (
@@ -3,6 +3,7 @@ import { useEffect } from "react";
3
3
  import { EWalletObserverEvents } from "../../../../@types/events.js";
4
4
  import { WalletObserver } from "../../../../classes/WalletObserver.class.js";
5
5
  import { TWalletProviderHooks } from "../../../contexts/observer/index.js";
6
+ import { useWalletObserverState } from "../useWalletObserverState.js";
6
7
 
7
8
  /**
8
9
  * Internal use only. This is run in every WalletObserverProvider
@@ -15,7 +16,7 @@ import { TWalletProviderHooks } from "../../../contexts/observer/index.js";
15
16
  */
16
17
  export const useProviderEventListeners = (
17
18
  observer: WalletObserver,
18
- syncWallet: () => Promise<void>,
19
+ state: ReturnType<typeof useWalletObserverState>,
19
20
  hooks?: TWalletProviderHooks
20
21
  ) => {
21
22
  /**
@@ -80,26 +81,10 @@ export const useProviderEventListeners = (
80
81
  * Ensure the wallet syncs on connect and disconnect.
81
82
  */
82
83
  useEffect(() => {
83
- window.addEventListener("focus", syncWallet);
84
-
85
- observer.addEventListener(
86
- EWalletObserverEvents.CONNECT_WALLET_END,
87
- syncWallet
88
- );
89
-
90
- observer.addEventListener(EWalletObserverEvents.DISCONNECT, syncWallet);
84
+ window.addEventListener("focus", state.syncWallet);
91
85
 
92
86
  return () => {
93
- window.addEventListener("focus", syncWallet);
94
- observer.removeEventListener(
95
- EWalletObserverEvents.CONNECT_WALLET_END,
96
- syncWallet
97
- );
98
-
99
- observer.removeEventListener(
100
- EWalletObserverEvents.DISCONNECT,
101
- syncWallet
102
- );
87
+ window.addEventListener("focus", state.syncWallet);
103
88
  };
104
- }, [observer, syncWallet]);
89
+ }, [state.syncWallet]);
105
90
  };
@@ -1,7 +1,6 @@
1
1
  import type { TransactionUnspentOutput } from "@cardano-sdk/core/dist/cjs/Serialization/index.js";
2
2
  import { AssetAmount } from "@sundaeswap/asset";
3
3
  import { useCallback, useState } from "react";
4
- import { unstable_batchedUpdates } from "react-dom";
5
4
 
6
5
  import {
7
6
  TAssetAmountMap,
@@ -38,92 +37,112 @@ export const useWalletObserverState = (observer: WalletObserver) => {
38
37
  const [collateral, setCollateral] = useState<TransactionUnspentOutput[]>();
39
38
  const [ready, setReady] = useState(false);
40
39
  const [isCip45, setIsCip45] = useState(false);
40
+ const [switching, setSwitching] = useState(false);
41
+
42
+ const disconnect = useCallback(() => {
43
+ // Reset observer state.
44
+ observer.disconnect();
45
+
46
+ // Reset state.
47
+ setAdaBalance(new AssetAmount(0n));
48
+ setBalance(new WalletBalanceMap(observer));
49
+ setHandleMetadata(new WalletAssetMap());
50
+ setUsedAddresses([]);
51
+ setUnusedAddresses([]);
52
+ setActiveWallet(undefined);
53
+ setNetwork(undefined);
54
+ setUtxos(undefined);
55
+ setCollateral(undefined);
56
+ setReady(false);
57
+ setIsCip45(false);
58
+ }, [observer]);
41
59
 
42
60
  const syncWallet = useCallback(async () => {
43
- if (observer.isSyncing()) {
61
+ if (observer.isSyncing() || !observer.hasActiveConnection()) {
44
62
  return;
45
63
  }
46
64
 
47
65
  const newWallet = observer.getActiveWallet();
48
-
49
66
  if (!newWallet) {
50
- unstable_batchedUpdates(() => {
51
- setAdaBalance(new AssetAmount(0n));
52
- setBalance(new WalletBalanceMap(observer));
53
- setUsedAddresses([]);
54
- setUnusedAddresses([]);
55
- setActiveWallet(undefined);
56
- setNetwork(undefined);
57
- setUtxos(undefined);
58
- setCollateral(undefined);
59
- });
67
+ disconnect();
60
68
  return;
61
69
  }
62
70
 
63
71
  const freshData = await observer.sync();
64
72
 
65
- unstable_batchedUpdates(() => {
66
- setActiveWallet((prevWallet) =>
67
- newWallet === prevWallet ? prevWallet : newWallet
68
- );
69
-
70
- const newAdaBalance = freshData.balanceMap.get(
71
- WalletObserver.ADA_ASSET_ID
72
- );
73
- if (newAdaBalance) {
74
- setAdaBalance((prevBalance) =>
75
- prevBalance.amount === newAdaBalance.amount
76
- ? prevBalance
77
- : newAdaBalance
78
- );
79
- }
73
+ setActiveWallet((prevWallet) =>
74
+ newWallet === prevWallet ? prevWallet : newWallet
75
+ );
80
76
 
81
- setBalance((prevBalance) =>
82
- areAssetMapsEqual(prevBalance, freshData.balanceMap)
77
+ const newAdaBalance = freshData.balanceMap.get(WalletObserver.ADA_ASSET_ID);
78
+ if (newAdaBalance) {
79
+ setAdaBalance((prevBalance) =>
80
+ prevBalance.amount === newAdaBalance.amount
83
81
  ? prevBalance
84
- : freshData.balanceMap
85
- );
86
-
87
- setUsedAddresses((prevValue) =>
88
- JSON.stringify(prevValue) === JSON.stringify(freshData.usedAddresses)
89
- ? prevValue
90
- : freshData.usedAddresses
91
- );
92
-
93
- setUnusedAddresses((prevValue) =>
94
- JSON.stringify(prevValue) === JSON.stringify(freshData.unusedAddresses)
95
- ? prevValue
96
- : freshData.unusedAddresses
82
+ : newAdaBalance
97
83
  );
84
+ }
98
85
 
99
- setNetwork((prevValue) =>
100
- prevValue === freshData.network ? prevValue : freshData.network
101
- );
86
+ setBalance((prevBalance) =>
87
+ areAssetMapsEqual(prevBalance, freshData.balanceMap)
88
+ ? prevBalance
89
+ : freshData.balanceMap
90
+ );
91
+
92
+ setUsedAddresses((prevValue) =>
93
+ JSON.stringify(prevValue) === JSON.stringify(freshData.usedAddresses)
94
+ ? prevValue
95
+ : freshData.usedAddresses
96
+ );
97
+
98
+ setUnusedAddresses((prevValue) =>
99
+ JSON.stringify(prevValue) === JSON.stringify(freshData.unusedAddresses)
100
+ ? prevValue
101
+ : freshData.unusedAddresses
102
+ );
103
+
104
+ setNetwork((prevValue) =>
105
+ prevValue === freshData.network ? prevValue : freshData.network
106
+ );
107
+
108
+ setUtxos((prevValue) => {
109
+ const prevValueRep = prevValue?.map((v) => v.toCbor());
110
+ const newValueRep = freshData.utxos?.map((v) => v.toCbor());
111
+ if (prevValueRep !== newValueRep) {
112
+ return freshData.utxos;
113
+ }
102
114
 
103
- setUtxos((prevValue) => {
104
- const prevValueRep = prevValue?.map((v) => v.toCbor());
105
- const newValueRep = freshData.utxos?.map((v) => v.toCbor());
106
- if (prevValueRep !== newValueRep) {
107
- return freshData.utxos;
108
- }
115
+ return prevValue;
116
+ });
109
117
 
110
- return prevValue;
111
- });
118
+ setCollateral((prevValue) => {
119
+ const prevValueRep = prevValue?.map((v) => v.toCbor());
120
+ const newValueRep = freshData.utxos?.map((v) => v.toCbor());
121
+ if (prevValueRep !== newValueRep) {
122
+ return freshData.utxos;
123
+ }
112
124
 
113
- setCollateral((prevValue) => {
114
- const prevValueRep = prevValue?.map((v) => v.toCbor());
115
- const newValueRep = freshData.utxos?.map((v) => v.toCbor());
116
- if (prevValueRep !== newValueRep) {
117
- return freshData.utxos;
118
- }
125
+ return prevValue;
126
+ });
119
127
 
120
- return prevValue;
121
- });
128
+ setReady(true);
129
+ setIsCip45(newWallet.includes("p2p"));
130
+ }, [observer, disconnect]);
131
+
132
+ const connectWallet = useCallback(
133
+ async (wallet: TSupportedWalletExtensions) => {
134
+ if (
135
+ observer.hasActiveConnection() &&
136
+ wallet !== observer.getActiveWallet()
137
+ ) {
138
+ setSwitching(true);
139
+ }
122
140
 
123
- setReady(true);
124
- setIsCip45(newWallet.includes("p2p"));
125
- });
126
- }, [observer]);
141
+ await observer.connectWallet(wallet).then(syncWallet);
142
+ setSwitching(false);
143
+ },
144
+ [observer, setSwitching]
145
+ );
127
146
 
128
147
  return {
129
148
  activeWallet,
@@ -147,6 +166,10 @@ export const useWalletObserverState = (observer: WalletObserver) => {
147
166
  collateral,
148
167
  setCollateral,
149
168
  syncWallet,
169
+ disconnect,
170
+ connectWallet,
171
+ switching,
172
+ setSwitching,
150
173
  ready,
151
174
  setReady,
152
175
  };
@@ -75,7 +75,10 @@ export interface IWalletObserverState<
75
75
  setUnusedAddresses: Dispatch<SetStateAction<string[]>>;
76
76
  usedAddresses: string[];
77
77
  setUsedAddresses: Dispatch<SetStateAction<string[]>>;
78
+ switching: boolean;
78
79
  syncWallet: () => Promise<void>;
80
+ disconnect: () => void;
81
+ connectWallet: (wallet: TSupportedWalletExtensions) => Promise<void>;
79
82
  };
80
83
  }
81
84
 
@@ -33,45 +33,53 @@ export const useWalletHandles = <
33
33
  }
34
34
 
35
35
  try {
36
- const HandleClient = await import("@koralabs/adahandle-sdk");
37
- const context =
38
- state.network === 1
39
- ? HandleClient.HandleClientContext.MAINNET
40
- : HandleClient.HandleClientContext.PREVIEW;
41
-
42
- // @ts-ignore Type isn't exported from default.
43
- const sdk = new HandleClient({
44
- context,
45
- provider: new HandleClient.KoraLabsProvider(context),
46
- });
47
-
48
- // Restore once SDK updated
49
- const walletHandlesWithDataArray = [...walletHandles.entries()];
50
- const walletHandleDataArray: IHandle[] = await sdk
51
- .provider()
52
- .getAllDataBatch(
53
- walletHandlesWithDataArray.map(([key]) => ({
54
- value: key.split(".")[1],
55
- }))
56
- );
57
-
58
- walletHandlesWithDataArray.forEach(([key, asset]) => {
59
- const matchingData = walletHandleDataArray.find(
60
- ({ hex }) => hex === key.split(".")[1]
61
- ) as IHandle;
62
-
63
- walletHandles.set(
64
- normalizeAssetIdWithDot(key),
65
- asset
66
- .withMetadata({
67
- ...matchingData,
68
- ...asset.metadata,
69
- assetId: normalizeAssetIdWithDot(asset.metadata.assetId),
70
- decimals: 0,
71
- })
72
- .withAmount(1n)
73
- );
74
- });
36
+ await import("@koralabs/adahandle-sdk").then(
37
+ async ({
38
+ default: HandleClient,
39
+ HandleClientContext,
40
+ KoraLabsProvider,
41
+ }) => {
42
+ setLoadingHandles(true);
43
+ const context =
44
+ state.network === 1
45
+ ? HandleClientContext.MAINNET
46
+ : HandleClientContext.PREVIEW;
47
+
48
+ // @ts-ignore Type isn't exported from default.
49
+ const sdk = new HandleClient({
50
+ context,
51
+ provider: new KoraLabsProvider(context),
52
+ });
53
+
54
+ // Restore once SDK updated
55
+ const walletHandlesWithDataArray = [...walletHandles.entries()];
56
+ const walletHandleDataArray: IHandle[] = await sdk
57
+ .provider()
58
+ .getAllDataBatch(
59
+ walletHandlesWithDataArray.map(([key]) => ({
60
+ value: key.split(".")[1],
61
+ }))
62
+ );
63
+
64
+ walletHandlesWithDataArray.forEach(([key, asset]) => {
65
+ const matchingData = walletHandleDataArray.find(
66
+ ({ hex }) => hex === key.split(".")[1]
67
+ ) as IHandle;
68
+
69
+ walletHandles.set(
70
+ normalizeAssetIdWithDot(key),
71
+ asset
72
+ .withMetadata({
73
+ ...matchingData,
74
+ ...asset.metadata,
75
+ assetId: normalizeAssetIdWithDot(asset.metadata.assetId),
76
+ decimals: 0,
77
+ })
78
+ .withAmount(1n)
79
+ );
80
+ });
81
+ }
82
+ );
75
83
 
76
84
  return walletHandles;
77
85
  } catch (e) {
@@ -79,35 +87,34 @@ export const useWalletHandles = <
79
87
  return walletHandles;
80
88
  }
81
89
  // We only want to update the callback if the Handle keys change.
82
- }, [state.balance, setLoadingHandles]);
90
+ }, [state.balance]);
83
91
 
84
92
  useEffect(() => {
85
- syncHandles()
86
- .then((newHandles) => {
87
- setHandles((prevHandles) => {
88
- let handleMetadataChanged = false;
89
-
90
- if (newHandles.size !== prevHandles?.size) {
91
- handleMetadataChanged = true;
92
- } else {
93
- for (const [key, val] of newHandles) {
94
- if (
95
- !prevHandles.has(key) ||
96
- prevHandles.get(key)?.amount !== val?.amount
97
- ) {
98
- handleMetadataChanged = true;
99
- }
93
+ syncHandles().then((newHandles) => {
94
+ setHandles((prevHandles) => {
95
+ let handleMetadataChanged = false;
96
+
97
+ if (newHandles.size !== prevHandles?.size) {
98
+ handleMetadataChanged = true;
99
+ } else {
100
+ for (const [key, val] of newHandles) {
101
+ if (
102
+ !prevHandles.has(key) ||
103
+ prevHandles.get(key)?.amount !== val?.amount
104
+ ) {
105
+ handleMetadataChanged = true;
100
106
  }
101
107
  }
108
+ }
102
109
 
103
- if (!handleMetadataChanged) {
104
- return prevHandles;
105
- }
110
+ if (!handleMetadataChanged) {
111
+ return prevHandles;
112
+ }
106
113
 
107
- return newHandles;
108
- });
109
- })
110
- .then(() => setLoadingHandles((prevValue) => !prevValue));
114
+ return newHandles;
115
+ });
116
+ setLoadingHandles(() => false);
117
+ });
111
118
  }, [memoizedHandleDep, syncHandles, setHandles, setLoadingHandles]);
112
119
 
113
120
  const data = useMemo(
@@ -29,9 +29,12 @@ export const useWalletObserver = <
29
29
  utxos: state.utxos,
30
30
  collateral: state.collateral,
31
31
  observer: state.observer,
32
- syncWallet: state.syncWallet,
33
32
  unusedAddresses: state.unusedAddresses,
34
33
  usedAddresses: state.usedAddresses,
34
+ syncWallet: state.syncWallet,
35
+ disconnect: state.disconnect,
36
+ connectWallet: state.connectWallet,
37
+ switching: state.switching,
35
38
  };
36
39
 
37
40
  return result;
@@ -44,12 +47,15 @@ export const useWalletObserver = <
44
47
  state.network,
45
48
  state.observer,
46
49
  state.syncWallet,
50
+ state.disconnect,
51
+ state.connectWallet,
47
52
  state.unusedAddresses,
48
53
  state.usedAddresses,
49
54
  state.utxos,
50
55
  state.collateral,
51
56
  state.ready,
52
57
  state.isCip45,
58
+ state.switching,
53
59
  ]);
54
60
 
55
61
  return memoizedState;