@rango-dev/widget-embedded 0.41.1-next.4 → 0.41.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rango-dev/widget-embedded",
3
- "version": "0.41.1-next.4",
3
+ "version": "0.41.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "source": "./src/index.ts",
@@ -1,4 +1,5 @@
1
- import type { RouteEventData, StepEventData } from '../..';
1
+ import type { ConnectedWallet, RouteEventData, StepEventData } from '../..';
2
+ import type { Asset } from 'rango-types';
2
3
 
3
4
  import {
4
5
  isApprovalTX,
@@ -15,11 +16,21 @@ import { useNotificationStore } from '../../store/notification';
15
16
 
16
17
  export function useSubscribeToWidgetEvents() {
17
18
  const setNotification = useNotificationStore.use.setNotification();
18
- const { connectedWallets, fetchBalances } = useAppStore();
19
+ const {
20
+ connectedWallets,
21
+ fetchBalances,
22
+ customTokens: getCustomTokens,
23
+ } = useAppStore();
19
24
 
20
25
  useEffect(() => {
21
26
  const handleStepEvent = (widgetEvent: StepEventData) => {
22
27
  const { event, step, route } = widgetEvent;
28
+
29
+ /**
30
+ * Determine if we should refetch balances:
31
+ * - When a transaction is sent (TX_SENT) and it's not an approval transaction.
32
+ * - When a step succeeds.
33
+ */
23
34
  const shouldRefetchBalance =
24
35
  (event.type === StepEventType.TX_EXECUTION &&
25
36
  event.status === StepExecutionEventStatus.TX_SENT &&
@@ -27,6 +38,12 @@ export function useSubscribeToWidgetEvents() {
27
38
  event.type === StepEventType.SUCCEEDED;
28
39
 
29
40
  if (shouldRefetchBalance) {
41
+ const fetchBalanceAccounts: ConnectedWallet[] = [];
42
+
43
+ /**
44
+ * Identify the wallet corresponding to the `from` blockchain and match it with a connected wallet.
45
+ * If found, add it to the balance fetch list.
46
+ */
30
47
  const fromWallet = route.wallets[step?.fromBlockchain];
31
48
  if (fromWallet) {
32
49
  const fromAccount = connectedWallets.find(
@@ -37,10 +54,14 @@ export function useSubscribeToWidgetEvents() {
37
54
  connectedWallet.chain === step?.fromBlockchain
38
55
  );
39
56
  if (fromAccount) {
40
- void fetchBalances([fromAccount]);
57
+ fetchBalanceAccounts.push(fromAccount);
41
58
  }
42
59
  }
43
60
 
61
+ /**
62
+ * If the transaction is cross-chain (`fromBlockchain !== toBlockchain`),
63
+ * find and add the `to` blockchain wallet to the balance fetch list.
64
+ */
44
65
  if (step?.fromBlockchain !== step?.toBlockchain) {
45
66
  const toWallet = route.wallets[step?.toBlockchain];
46
67
  if (toWallet) {
@@ -52,10 +73,41 @@ export function useSubscribeToWidgetEvents() {
52
73
  connectedWallet.chain === step?.toBlockchain
53
74
  );
54
75
  if (toAccount) {
55
- void fetchBalances([toAccount]);
76
+ fetchBalanceAccounts.push(toAccount);
56
77
  }
57
78
  }
58
79
  }
80
+
81
+ if (fetchBalanceAccounts.length > 0) {
82
+ const customTokens = getCustomTokens();
83
+ const stepAssets: Asset[] = [
84
+ {
85
+ blockchain: step.fromBlockchain,
86
+ address: step.fromSymbolAddress,
87
+ symbol: step.fromSymbol,
88
+ },
89
+ {
90
+ blockchain: step.toBlockchain,
91
+ address: step.toSymbolAddress,
92
+ symbol: step.toSymbol,
93
+ },
94
+ ];
95
+ const selectedCustomTokens = stepAssets.filter((asset) =>
96
+ customTokens.some(
97
+ (token) =>
98
+ token.blockchain === asset.blockchain &&
99
+ token.address?.toLocaleLowerCase() ===
100
+ asset.address?.toLocaleLowerCase() &&
101
+ token.symbol?.toLocaleLowerCase() ===
102
+ asset.symbol?.toLocaleLowerCase()
103
+ )
104
+ );
105
+
106
+ void fetchBalances(fetchBalanceAccounts, {
107
+ selectedCustomTokens,
108
+ shouldFetchCustomTokens: selectedCustomTokens.length > 0,
109
+ });
110
+ }
59
111
  }
60
112
 
61
113
  setNotification(event, route);
@@ -189,7 +189,7 @@ export const createSettingsSlice: StateCreator<
189
189
  });
190
190
  },
191
191
  setCustomToken: (token) => {
192
- void get().fetchCustomTokensBalance({
192
+ void get().fetchCustomTokensBalances({
193
193
  tokens: [token],
194
194
  connectedWallets: get().connectedWallets,
195
195
  });
@@ -121,10 +121,17 @@ export interface WalletsSlice {
121
121
  ) => void;
122
122
  clearConnectedWallet: () => void;
123
123
  fetchBalances: (
124
+ accounts: Wallet[],
125
+ options?: {
126
+ shouldFetchCustomTokens?: boolean;
127
+ selectedCustomTokens?: Asset[];
128
+ }
129
+ ) => Promise<void>;
130
+ fetchMainTokensBalances: (
124
131
  accounts: Wallet[],
125
132
  options?: { retryOnFailedBalances?: boolean }
126
133
  ) => Promise<void>;
127
- fetchCustomTokensBalance: (params: {
134
+ fetchCustomTokensBalances: (params: {
128
135
  tokens: Asset[];
129
136
  connectedWallets: Wallet[];
130
137
  }) => Promise<void>;
@@ -299,7 +306,7 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
299
306
  });
300
307
  }
301
308
  },
302
- fetchCustomTokensBalance: async (params) => {
309
+ fetchCustomTokensBalances: async (params) => {
303
310
  const { tokens, connectedWallets } = params;
304
311
 
305
312
  const tokensByBlockchain = tokens.reduce<{ [key: string]: Asset[] }>(
@@ -436,10 +443,6 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
436
443
  get().addConnectedWallet(accounts, namespace);
437
444
 
438
445
  void get().fetchBalances(accounts);
439
- void get().fetchCustomTokensBalance({
440
- tokens: get().customTokens(),
441
- connectedWallets: accounts,
442
- });
443
446
  },
444
447
  removeBalancesForWallet: (walletType, options) => {
445
448
  const partialCurrentState = {
@@ -581,6 +584,20 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
581
584
  },
582
585
  clearConnectedWallet: () => set({ connectedWallets: [] }),
583
586
  fetchBalances: async (accounts, options) => {
587
+ const { shouldFetchCustomTokens = true, selectedCustomTokens } =
588
+ options || {};
589
+ await get().fetchMainTokensBalances(accounts);
590
+ if (shouldFetchCustomTokens) {
591
+ void get().fetchCustomTokensBalances({
592
+ tokens: selectedCustomTokens ?? get().customTokens(),
593
+ connectedWallets: accounts,
594
+ });
595
+ }
596
+ },
597
+ fetchMainTokensBalances: async (accounts, options) => {
598
+ if (accounts.length === 0) {
599
+ return;
600
+ }
584
601
  // All the `accounts` have same `walletType` so we can pick the first one.
585
602
  const walletType = accounts[0].walletType;
586
603
 
@@ -602,22 +619,6 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
602
619
  const walletsDetails = response.wallets;
603
620
 
604
621
  if (walletsDetails) {
605
- const { retryOnFailedBalances = true } = options || {};
606
- if (retryOnFailedBalances) {
607
- const failedWallets: Wallet[] = walletsDetails
608
- .filter((wallet) => wallet.failed)
609
- .map((wallet) => ({
610
- chain: wallet.blockChain,
611
- walletType: walletType,
612
- address: wallet.address,
613
- }));
614
- if (failedWallets.length > 0) {
615
- void get().fetchBalances(failedWallets, {
616
- retryOnFailedBalances: false,
617
- });
618
- }
619
- }
620
-
621
622
  let nextBalances: BalanceState = get()._balances;
622
623
  let nextAggregatedBalances: AggregatedBalanceState =
623
624
  get()._aggregatedBalances;
@@ -691,6 +692,27 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
691
692
  }));
692
693
 
693
694
  get().setConnectedWalletRetrievedData(accounts, walletsDetails);
695
+ /*
696
+ * We handle failed balance fetches after updating the state with successful ones.
697
+ * This ensures that successful balance updates are immediately available to the UI,
698
+ * while failed ones are retried in the background without blocking the main flow.
699
+ * The retry is only attempted once to prevent infinite loops.
700
+ */
701
+ const { retryOnFailedBalances = true } = options || {};
702
+ if (retryOnFailedBalances) {
703
+ const failedWallets: Wallet[] = walletsDetails
704
+ .filter((wallet) => wallet.failed)
705
+ .map((wallet) => ({
706
+ chain: wallet.blockChain,
707
+ walletType: walletType,
708
+ address: wallet.address,
709
+ }));
710
+ if (failedWallets.length > 0) {
711
+ await get().fetchMainTokensBalances(failedWallets, {
712
+ retryOnFailedBalances: false,
713
+ });
714
+ }
715
+ }
694
716
  } else {
695
717
  get().setConnectedWalletHasError(accounts);
696
718
  console.error(