@rango-dev/widget-embedded 0.39.1-next.9 → 0.40.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/CHANGELOG.md +42 -0
- package/dist/components/SwapDetailsModal/SwapDetailsCompleteModal.d.ts.map +1 -1
- package/dist/components/SwapDetailsModal/SwapDetailsModal.styles.d.ts +160 -0
- package/dist/components/SwapDetailsModal/SwapDetailsModal.styles.d.ts.map +1 -1
- package/dist/constants/profileBanner.d.ts +3 -0
- package/dist/constants/profileBanner.d.ts.map +1 -0
- package/dist/constants/wallets.d.ts +1 -0
- package/dist/constants/wallets.d.ts.map +1 -1
- package/dist/containers/Wallets/Wallets.d.ts.map +1 -1
- package/dist/containers/Wallets/Wallets.helpers.d.ts +4 -0
- package/dist/containers/Wallets/Wallets.helpers.d.ts.map +1 -0
- package/dist/containers/Wallets/Wallets.types.d.ts +6 -2
- package/dist/containers/Wallets/Wallets.types.d.ts.map +1 -1
- package/dist/containers/Wallets/useUpdates.d.ts +13 -0
- package/dist/containers/Wallets/useUpdates.d.ts.map +1 -0
- package/dist/hooks/useSubscribeToWidgetEvents/useSubscribeToWidgetEvents.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -4
- package/dist/store/middlewares/keepLastUpdated.d.ts +8 -0
- package/dist/store/middlewares/keepLastUpdated.d.ts.map +1 -0
- package/dist/store/slices/wallets.d.ts +19 -13
- package/dist/store/slices/wallets.d.ts.map +1 -1
- package/dist/store/utils/wallets.d.ts +3 -3
- package/dist/store/utils/wallets.d.ts.map +1 -1
- package/dist/utils/common.d.ts +5 -0
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/widget-embedded.build.json +1 -1
- package/package.json +11 -11
- package/src/components/ConfirmWalletsModal/WalletList.tsx +1 -1
- package/src/components/SwapDetailsModal/SwapDetailsCompleteModal.tsx +14 -7
- package/src/components/SwapDetailsModal/SwapDetailsModal.styles.ts +4 -0
- package/src/constants/profileBanner.ts +3 -0
- package/src/constants/wallets.ts +2 -0
- package/src/containers/Inputs/Inputs.tsx +1 -1
- package/src/containers/Wallets/Wallets.helpers.ts +26 -0
- package/src/containers/Wallets/Wallets.tsx +23 -127
- package/src/containers/Wallets/Wallets.types.ts +16 -2
- package/src/containers/Wallets/useUpdates.ts +240 -0
- package/src/hooks/useSubscribeToWidgetEvents/useSubscribeToWidgetEvents.ts +19 -9
- package/src/store/middlewares/keepLastUpdated.ts +19 -0
- package/src/store/slices/wallets.ts +546 -414
- package/src/store/utils/wallets.ts +12 -11
- package/src/utils/common.ts +24 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { AppStoreState } from './types';
|
|
2
|
+
import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';
|
|
2
3
|
import type { Token, WalletDetail } from 'rango-sdk';
|
|
3
|
-
import type { StateCreator } from 'zustand';
|
|
4
4
|
|
|
5
5
|
import BigNumber from 'bignumber.js';
|
|
6
6
|
|
|
7
7
|
import { ZERO } from '../../constants/numbers';
|
|
8
|
+
import { BALANCE_SEPARATOR } from '../../constants/wallets';
|
|
8
9
|
import { eventEmitter } from '../../services/eventEmitter';
|
|
9
10
|
import { httpService } from '../../services/httpService';
|
|
10
11
|
import {
|
|
@@ -13,7 +14,9 @@ import {
|
|
|
13
14
|
WalletEventTypes,
|
|
14
15
|
WidgetEvents,
|
|
15
16
|
} from '../../types';
|
|
17
|
+
import { memoizedResult } from '../../utils/common';
|
|
16
18
|
import { isAccountAndWalletMatched } from '../../utils/wallets';
|
|
19
|
+
import { keepLastUpdated } from '../middlewares/keepLastUpdated';
|
|
17
20
|
import {
|
|
18
21
|
createAssetKey,
|
|
19
22
|
createBalanceKey,
|
|
@@ -27,11 +30,12 @@ type WalletAddress = string;
|
|
|
27
30
|
type TokenAddress = string;
|
|
28
31
|
type TokenSymbol = string;
|
|
29
32
|
type BlockchainId = string;
|
|
30
|
-
/** format: `BlockchainId
|
|
31
|
-
export type AssetKey =
|
|
32
|
-
|
|
33
|
+
/** format: `BlockchainId${BALANCE_SEPARATOR}TokenAddress${BALANCE_SEPARATOR}TokenSymbol` */
|
|
34
|
+
export type AssetKey =
|
|
35
|
+
`${BlockchainId}${typeof BALANCE_SEPARATOR}${TokenAddress}${typeof BALANCE_SEPARATOR}${TokenSymbol}`;
|
|
36
|
+
/** format: `BlockchainId${BALANCE_SEPARATOR}TokenAddress${BALANCE_SEPARATOR}TokenSymbol${BALANCE_SEPARATOR}WalletAddress` */
|
|
33
37
|
export type BalanceKey =
|
|
34
|
-
`${BlockchainId}
|
|
38
|
+
`${BlockchainId}${typeof BALANCE_SEPARATOR}${TokenAddress}${typeof BALANCE_SEPARATOR}${TokenSymbol}${typeof BALANCE_SEPARATOR}${WalletAddress}`;
|
|
35
39
|
|
|
36
40
|
export type BalanceState = {
|
|
37
41
|
[key: BalanceKey]: Balance;
|
|
@@ -45,6 +49,7 @@ export interface ConnectedWallet extends Wallet {
|
|
|
45
49
|
selected: boolean;
|
|
46
50
|
loading: boolean;
|
|
47
51
|
error: boolean;
|
|
52
|
+
namespace?: Namespace;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
interface DeprecatedTokenBalance {
|
|
@@ -79,31 +84,41 @@ export interface WalletsSlice {
|
|
|
79
84
|
_aggregatedBalances: AggregatedBalanceState;
|
|
80
85
|
connectedWallets: ConnectedWallet[];
|
|
81
86
|
fetchingWallets: boolean;
|
|
87
|
+
lastUpdatedAt: number;
|
|
82
88
|
|
|
83
|
-
setConnectedWalletAsRefetching: (
|
|
84
|
-
setConnectedWalletHasError: (
|
|
89
|
+
setConnectedWalletAsRefetching: (accounts: Wallet[]) => void;
|
|
90
|
+
setConnectedWalletHasError: (accounts: Wallet[]) => void;
|
|
85
91
|
setConnectedWalletRetrievedData: (
|
|
86
|
-
|
|
92
|
+
accounts: Wallet[],
|
|
87
93
|
walletsDetails: WalletDetail[]
|
|
88
94
|
) => void;
|
|
89
95
|
removeBalancesForWallet: (
|
|
90
96
|
walletType: string,
|
|
91
97
|
options?: {
|
|
92
98
|
chains?: string[];
|
|
99
|
+
namespaces?: Namespace[];
|
|
93
100
|
}
|
|
94
101
|
) => void;
|
|
95
|
-
addConnectedWallet: (accounts: Wallet[]) => void;
|
|
102
|
+
addConnectedWallet: (accounts: Wallet[], namespace?: Namespace) => void;
|
|
96
103
|
setWalletsAsSelected: (
|
|
97
104
|
wallets: { walletType: string; chain: string }[]
|
|
98
105
|
) => void;
|
|
99
106
|
/**
|
|
100
107
|
* Add new accounts to store and fetch balances for them.
|
|
101
108
|
*/
|
|
102
|
-
newWalletConnected: (
|
|
109
|
+
newWalletConnected: (
|
|
110
|
+
accounts: Wallet[],
|
|
111
|
+
namespace?: Namespace
|
|
112
|
+
) => Promise<void>;
|
|
113
|
+
disconnectNamespaces: (walletType: string, namespaces: Namespace[]) => void;
|
|
103
114
|
/**
|
|
104
115
|
* Disconnect a wallet and clean up balances after that.
|
|
105
116
|
*/
|
|
106
117
|
disconnectWallet: (walletType: string) => void;
|
|
118
|
+
_changeSelectedWalletIfNeededOnRemove: (
|
|
119
|
+
walletType: string,
|
|
120
|
+
options?: { namespaces?: Namespace[] }
|
|
121
|
+
) => void;
|
|
107
122
|
clearConnectedWallet: () => void;
|
|
108
123
|
fetchBalances: (
|
|
109
124
|
accounts: Wallet[],
|
|
@@ -120,472 +135,589 @@ export interface WalletsSlice {
|
|
|
120
135
|
getConnectedWalletsDetails: () => DeprecatedWalletDetail[];
|
|
121
136
|
}
|
|
122
137
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
138
|
+
const memoizedConnectedWalletsWithNestedBalances = memoizedResult();
|
|
139
|
+
export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
140
|
+
(set, get) => ({
|
|
141
|
+
_balances: {},
|
|
142
|
+
_aggregatedBalances: {},
|
|
143
|
+
connectedWallets: [],
|
|
144
|
+
fetchingWallets: false,
|
|
145
|
+
lastUpdatedAt: +new Date(),
|
|
146
|
+
|
|
147
|
+
// Actions
|
|
148
|
+
setConnectedWalletAsRefetching: (accounts: Wallet[]) => {
|
|
149
|
+
set((state) => {
|
|
150
|
+
return {
|
|
151
|
+
fetchingWallets: true,
|
|
152
|
+
connectedWallets: state.connectedWallets.map((connectedWallet) => {
|
|
153
|
+
if (
|
|
154
|
+
accounts.find((account) =>
|
|
155
|
+
isAccountAndWalletMatched(account, connectedWallet)
|
|
156
|
+
)
|
|
157
|
+
) {
|
|
158
|
+
return {
|
|
159
|
+
...connectedWallet,
|
|
160
|
+
loading: true,
|
|
161
|
+
error: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return connectedWallet;
|
|
166
|
+
}),
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
setConnectedWalletRetrievedData: (
|
|
171
|
+
accounts: Wallet[],
|
|
172
|
+
walletsDetails: WalletDetail[]
|
|
173
|
+
) => {
|
|
174
|
+
set((state) => {
|
|
175
|
+
return {
|
|
176
|
+
fetchingWallets: false,
|
|
177
|
+
connectedWallets: state.connectedWallets.map((connectedWallet) => {
|
|
178
|
+
if (
|
|
179
|
+
accounts.find((account) =>
|
|
180
|
+
isAccountAndWalletMatched(account, connectedWallet)
|
|
181
|
+
)
|
|
182
|
+
) {
|
|
183
|
+
return {
|
|
184
|
+
...connectedWallet,
|
|
185
|
+
loading: false,
|
|
186
|
+
error: false,
|
|
187
|
+
explorerUrl:
|
|
188
|
+
matchWalletDetailsWithConnectedWallet(
|
|
189
|
+
connectedWallet,
|
|
190
|
+
walletsDetails
|
|
191
|
+
)?.explorerUrl || connectedWallet.explorerUrl,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return connectedWallet;
|
|
196
|
+
}),
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
setConnectedWalletHasError: (accounts: Wallet[]) => {
|
|
201
|
+
set((state) => {
|
|
202
|
+
return {
|
|
203
|
+
fetchingWallets: false,
|
|
204
|
+
connectedWallets: state.connectedWallets.map((connectedWallet) => {
|
|
205
|
+
if (
|
|
206
|
+
accounts.find((account) =>
|
|
207
|
+
isAccountAndWalletMatched(account, connectedWallet)
|
|
208
|
+
)
|
|
209
|
+
) {
|
|
210
|
+
return {
|
|
211
|
+
...connectedWallet,
|
|
212
|
+
loading: false,
|
|
213
|
+
error: true,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return connectedWallet;
|
|
218
|
+
}),
|
|
219
|
+
};
|
|
220
|
+
});
|
|
221
|
+
},
|
|
222
|
+
addConnectedWallet: (accounts, namespace) => {
|
|
223
|
+
/*
|
|
224
|
+
* When we are going to add a new account, there are two thing that can be happens:
|
|
225
|
+
* 1. Wallet hasn't add yet.
|
|
226
|
+
* 2. Wallet has added, and there are some more account that needs to added to connected wallet. consider we've added an ETH and Pol account, then we need to add Arb account later as well.
|
|
227
|
+
*
|
|
228
|
+
* For handling this, we need to only keep not-added-account, then only add those.
|
|
229
|
+
*
|
|
230
|
+
* Note:
|
|
231
|
+
* The second option would be useful for hub particularly.
|
|
232
|
+
*/
|
|
233
|
+
const connectedWallets = get().connectedWallets;
|
|
234
|
+
const walletsNeedToBeAdded = accounts.filter(
|
|
235
|
+
(account) =>
|
|
236
|
+
!connectedWallets.some((connectedWallet) =>
|
|
237
|
+
isAccountAndWalletMatched(account, connectedWallet)
|
|
238
|
+
)
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
if (walletsNeedToBeAdded.length > 0) {
|
|
242
|
+
const newConnectedWallets: ConnectedWallet[] = walletsNeedToBeAdded.map(
|
|
243
|
+
(account) => {
|
|
244
|
+
/*
|
|
245
|
+
* When a wallet is connecting, we will check if there is any `selected` wallet before, if not, we will consider this new wallet as connected.
|
|
246
|
+
* In this way, when user tries to swap, we selected a wallet by default and don't need to do an extra click in ConfirmWalletModal
|
|
247
|
+
*/
|
|
248
|
+
const shouldMarkWalletAsSelected = !connectedWallets.some(
|
|
249
|
+
(connectedWallet) =>
|
|
250
|
+
connectedWallet.chain === account.chain &&
|
|
251
|
+
connectedWallet.selected &&
|
|
252
|
+
/**
|
|
253
|
+
* Sometimes, the connect function can be called multiple times for a particular wallet type when using the auto-connect feature.
|
|
254
|
+
* This check is there to make sure the chosen wallet doesn't end up unselected.
|
|
255
|
+
*/
|
|
256
|
+
connectedWallet.walletType !== account.walletType
|
|
257
|
+
);
|
|
147
258
|
|
|
148
|
-
return connectedWallet;
|
|
149
|
-
}),
|
|
150
|
-
};
|
|
151
|
-
});
|
|
152
|
-
},
|
|
153
|
-
setConnectedWalletRetrievedData: (
|
|
154
|
-
walletType: string,
|
|
155
|
-
walletsDetails: WalletDetail[]
|
|
156
|
-
) => {
|
|
157
|
-
set((state) => {
|
|
158
|
-
return {
|
|
159
|
-
fetchingWallets: false,
|
|
160
|
-
connectedWallets: state.connectedWallets.map((connectedWallet) => {
|
|
161
|
-
if (connectedWallet.walletType === walletType) {
|
|
162
259
|
return {
|
|
163
|
-
|
|
260
|
+
address: account.address,
|
|
261
|
+
chain: account.chain,
|
|
262
|
+
explorerUrl: null,
|
|
263
|
+
walletType: account.walletType,
|
|
264
|
+
selected: shouldMarkWalletAsSelected,
|
|
265
|
+
namespace: namespace,
|
|
164
266
|
loading: false,
|
|
165
267
|
error: false,
|
|
166
|
-
explorerUrl:
|
|
167
|
-
matchWalletDetailsWithConnectedWallet(
|
|
168
|
-
connectedWallet,
|
|
169
|
-
walletsDetails
|
|
170
|
-
)?.explorerUrl || connectedWallet.explorerUrl,
|
|
171
268
|
};
|
|
172
269
|
}
|
|
270
|
+
);
|
|
173
271
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
272
|
+
set((state) => {
|
|
273
|
+
/*
|
|
274
|
+
* If wallet connected before and only need to update the address we should remove the old value and then add new conncted value.
|
|
275
|
+
* This scenario happens when user wants to change account inside the wallet.
|
|
276
|
+
* So the assumption here is the wallet has only one active address for a blockchain at the moment.
|
|
277
|
+
*/
|
|
278
|
+
const connectedWalletsWithoutSameWalletAndBlockchain =
|
|
279
|
+
state.connectedWallets.filter((currentConnectedWallet) => {
|
|
280
|
+
return !newConnectedWallets.some(
|
|
281
|
+
(newConnectedWallet) =>
|
|
282
|
+
newConnectedWallet.walletType ===
|
|
283
|
+
currentConnectedWallet.walletType &&
|
|
284
|
+
newConnectedWallet.chain === currentConnectedWallet.chain
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
connectedWallets: [
|
|
290
|
+
...connectedWalletsWithoutSameWalletAndBlockchain,
|
|
291
|
+
...newConnectedWallets,
|
|
292
|
+
],
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
setWalletsAsSelected: (wallets) => {
|
|
298
|
+
const nextConnectedWalletsWithUpdatedSelectedStatus =
|
|
299
|
+
get().connectedWallets.map((connectedWallet) => {
|
|
300
|
+
const walletSelected = !!wallets.find(
|
|
301
|
+
(wallet) =>
|
|
302
|
+
wallet.chain === connectedWallet.chain &&
|
|
303
|
+
wallet.walletType !== connectedWallet.walletType &&
|
|
304
|
+
connectedWallet.selected
|
|
305
|
+
);
|
|
306
|
+
const walletNotSelected = !!wallets.find(
|
|
307
|
+
(wallet) =>
|
|
308
|
+
wallet.chain === connectedWallet.chain &&
|
|
309
|
+
wallet.walletType === connectedWallet.walletType &&
|
|
310
|
+
!connectedWallet.selected
|
|
311
|
+
);
|
|
312
|
+
if (walletSelected) {
|
|
313
|
+
return { ...connectedWallet, selected: false };
|
|
314
|
+
} else if (walletNotSelected) {
|
|
315
|
+
return { ...connectedWallet, selected: true };
|
|
190
316
|
}
|
|
191
317
|
|
|
192
318
|
return connectedWallet;
|
|
193
|
-
})
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
addConnectedWallet: (accounts: Wallet[]) => {
|
|
198
|
-
/*
|
|
199
|
-
* When we are going to add a new account, there are two thing that can be happens:
|
|
200
|
-
* 1. Wallet hasn't add yet.
|
|
201
|
-
* 2. Wallet has added, and there are some more account that needs to added to connected wallet. consider we've added an ETH and Pol account, then we need to add Arb account later as well.
|
|
202
|
-
*
|
|
203
|
-
* For handling this, we need to only keep not-added-account, then only add those.
|
|
204
|
-
*
|
|
205
|
-
* Note:
|
|
206
|
-
* The second option would be useful for hub particularly.
|
|
207
|
-
*/
|
|
208
|
-
const connectedWallets = get().connectedWallets;
|
|
209
|
-
const walletsNeedToBeAdded = accounts.filter(
|
|
210
|
-
(account) =>
|
|
211
|
-
!connectedWallets.some((connectedWallet) =>
|
|
212
|
-
isAccountAndWalletMatched(account, connectedWallet)
|
|
213
|
-
)
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
if (walletsNeedToBeAdded.length > 0) {
|
|
217
|
-
const newConnectedWallets = walletsNeedToBeAdded.map((account) => {
|
|
218
|
-
/*
|
|
219
|
-
* When a wallet is connecting, we will check if there is any `selected` wallet before, if not, we will consider this new wallet as connected.
|
|
220
|
-
* In this way, when user tries to swap, we selected a wallet by default and don't need to do an extra click in ConfirmWalletModal
|
|
221
|
-
*/
|
|
222
|
-
const shouldMarkWalletAsSelected = !connectedWallets.some(
|
|
223
|
-
(connectedWallet) =>
|
|
224
|
-
connectedWallet.chain === account.chain &&
|
|
225
|
-
connectedWallet.selected &&
|
|
226
|
-
/**
|
|
227
|
-
* Sometimes, the connect function can be called multiple times for a particular wallet type when using the auto-connect feature.
|
|
228
|
-
* This check is there to make sure the chosen wallet doesn't end up unselected.
|
|
229
|
-
*/
|
|
230
|
-
connectedWallet.walletType !== account.walletType
|
|
231
|
-
);
|
|
319
|
+
});
|
|
232
320
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
error: false,
|
|
242
|
-
};
|
|
321
|
+
set({
|
|
322
|
+
connectedWallets: nextConnectedWalletsWithUpdatedSelectedStatus,
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
newWalletConnected: async (accounts, namespace) => {
|
|
326
|
+
eventEmitter.emit(WidgetEvents.WalletEvent, {
|
|
327
|
+
type: WalletEventTypes.CONNECT,
|
|
328
|
+
payload: { walletType: accounts[0].walletType, accounts },
|
|
243
329
|
});
|
|
244
330
|
|
|
245
|
-
|
|
246
|
-
/*
|
|
247
|
-
* If wallet connected before and only need to update the address we should remove the old value and then add new conncted value.
|
|
248
|
-
* This scenario happens when user wants to change account inside the wallet.
|
|
249
|
-
* So the assumption here is the wallet has only one active address for a blockchain at the moment.
|
|
250
|
-
*/
|
|
251
|
-
const connectedWalletsWithoutSameWalletAndBlockchain =
|
|
252
|
-
state.connectedWallets.filter((currentConnectedWallet) => {
|
|
253
|
-
return !newConnectedWallets.some(
|
|
254
|
-
(newConnectedWallet) =>
|
|
255
|
-
newConnectedWallet.walletType ===
|
|
256
|
-
currentConnectedWallet.walletType &&
|
|
257
|
-
newConnectedWallet.chain === currentConnectedWallet.chain
|
|
258
|
-
);
|
|
259
|
-
});
|
|
331
|
+
get().addConnectedWallet(accounts, namespace);
|
|
260
332
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
wallet.chain === connectedWallet.chain &&
|
|
282
|
-
wallet.walletType === connectedWallet.walletType &&
|
|
283
|
-
!connectedWallet.selected
|
|
284
|
-
);
|
|
285
|
-
if (walletSelected) {
|
|
286
|
-
return { ...connectedWallet, selected: false };
|
|
287
|
-
} else if (walletNotSelected) {
|
|
288
|
-
return { ...connectedWallet, selected: true };
|
|
333
|
+
void get().fetchBalances(accounts);
|
|
334
|
+
},
|
|
335
|
+
removeBalancesForWallet: (walletType, options) => {
|
|
336
|
+
let walletsNeedsToBeRemoved = get().connectedWallets.filter(
|
|
337
|
+
(connectedWallet) => connectedWallet.walletType === walletType
|
|
338
|
+
);
|
|
339
|
+
/*
|
|
340
|
+
* We only need to delete balances where there is no connected wallets with same chain and address for that balance.
|
|
341
|
+
* Consider both Metamask and Solana having support for `0xblahblahblahblah` for Ethereum.
|
|
342
|
+
* If Phantom is disconnecting, we should keep the balance since Metamask has access to same address yet.
|
|
343
|
+
* So we only delete balance when there is no connected wallet that has access to that specific chain and address.
|
|
344
|
+
*/
|
|
345
|
+
get().connectedWallets.forEach((connectedWallet) => {
|
|
346
|
+
if (connectedWallet.walletType !== walletType) {
|
|
347
|
+
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
348
|
+
const isAnotherWalletHasSameAddressAndChain =
|
|
349
|
+
wallet.chain === connectedWallet.chain &&
|
|
350
|
+
wallet.address === connectedWallet.address;
|
|
351
|
+
return !isAnotherWalletHasSameAddressAndChain;
|
|
352
|
+
});
|
|
289
353
|
}
|
|
290
|
-
|
|
291
|
-
return connectedWallet;
|
|
292
354
|
});
|
|
293
355
|
|
|
294
|
-
|
|
295
|
-
connectedWallets: nextConnectedWalletsWithUpdatedSelectedStatus,
|
|
296
|
-
});
|
|
297
|
-
},
|
|
298
|
-
newWalletConnected: async (accounts) => {
|
|
299
|
-
eventEmitter.emit(WidgetEvents.WalletEvent, {
|
|
300
|
-
type: WalletEventTypes.CONNECT,
|
|
301
|
-
payload: { walletType: accounts[0].walletType, accounts },
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
get().addConnectedWallet(accounts);
|
|
305
|
-
|
|
306
|
-
void get().fetchBalances(accounts);
|
|
307
|
-
},
|
|
308
|
-
removeBalancesForWallet: (walletType, options) => {
|
|
309
|
-
let walletsNeedsToBeRemoved = get().connectedWallets.filter(
|
|
310
|
-
(connectedWallet) => connectedWallet.walletType === walletType
|
|
311
|
-
);
|
|
312
|
-
/*
|
|
313
|
-
* We only need to delete balances where there is no connected wallets with same chain and address for that balance.
|
|
314
|
-
* Consider both Metamask and Solana having support for `0xblahblahblahblah` for Ethereum.
|
|
315
|
-
* If Phantom is disconnecting, we should keep the balance since Metamask has access to same address yet.
|
|
316
|
-
* So we only delete balance when there is no connected wallet that has access to that specific chain and address.
|
|
317
|
-
*/
|
|
318
|
-
get().connectedWallets.forEach((connectedWallet) => {
|
|
319
|
-
if (connectedWallet.walletType !== walletType) {
|
|
356
|
+
if (!!options?.chains && options.chains.length > 0) {
|
|
320
357
|
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
321
|
-
|
|
322
|
-
wallet.chain === connectedWallet.chain &&
|
|
323
|
-
wallet.address === connectedWallet.address;
|
|
324
|
-
return !isAnotherWalletHasSameAddressAndChain;
|
|
358
|
+
return options.chains?.includes(wallet.chain);
|
|
325
359
|
});
|
|
326
360
|
}
|
|
327
|
-
});
|
|
328
361
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
362
|
+
if (!!options?.namespaces && options.namespaces.length > 0) {
|
|
363
|
+
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
364
|
+
if (wallet.namespace) {
|
|
365
|
+
return options.namespaces?.includes(wallet.namespace);
|
|
366
|
+
}
|
|
367
|
+
return false;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const nextBalancesState: BalanceState = {};
|
|
372
|
+
let nextAggregatedBalanceState: AggregatedBalanceState =
|
|
373
|
+
get()._aggregatedBalances;
|
|
374
|
+
const currentBalancesState = get()._balances;
|
|
375
|
+
const balanceKeys = Object.keys(currentBalancesState) as BalanceKey[];
|
|
376
|
+
|
|
377
|
+
balanceKeys.forEach((key) => {
|
|
378
|
+
const asset = extractAssetFromBalanceKey(key);
|
|
379
|
+
|
|
380
|
+
const shouldBalanceBeRemoved = !!walletsNeedsToBeRemoved.find(
|
|
381
|
+
(wallet) =>
|
|
382
|
+
createBalanceKey(wallet.address, {
|
|
383
|
+
address: asset.address,
|
|
384
|
+
blockchain: wallet.chain,
|
|
385
|
+
symbol: asset.symbol,
|
|
386
|
+
}) === key
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
// if a balance should be removed, we need to remove its caches in _aggregatedBalances as wel.
|
|
390
|
+
if (shouldBalanceBeRemoved) {
|
|
391
|
+
nextAggregatedBalanceState = removeBalanceFromAggregatedBalance(
|
|
392
|
+
nextAggregatedBalanceState,
|
|
393
|
+
key
|
|
394
|
+
);
|
|
395
|
+
} else {
|
|
396
|
+
nextBalancesState[key] = currentBalancesState[key];
|
|
397
|
+
}
|
|
332
398
|
});
|
|
333
|
-
}
|
|
334
399
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
(wallet) =>
|
|
346
|
-
createBalanceKey(wallet.address, {
|
|
347
|
-
address: asset.address,
|
|
348
|
-
blockchain: wallet.chain,
|
|
349
|
-
symbol: asset.symbol,
|
|
350
|
-
}) === key
|
|
351
|
-
);
|
|
400
|
+
set({
|
|
401
|
+
_balances: nextBalancesState,
|
|
402
|
+
_aggregatedBalances: nextAggregatedBalanceState,
|
|
403
|
+
});
|
|
404
|
+
},
|
|
405
|
+
disconnectNamespaces: (walletType, requestedNamesapces) => {
|
|
406
|
+
const isTargetWalletExistsInConnectedWallets =
|
|
407
|
+
get().connectedWallets.find(
|
|
408
|
+
(wallet) => wallet.walletType === walletType
|
|
409
|
+
);
|
|
352
410
|
|
|
353
|
-
if (
|
|
354
|
-
|
|
355
|
-
|
|
411
|
+
if (isTargetWalletExistsInConnectedWallets) {
|
|
412
|
+
// This should be called before updating connectedWallets since we need the old state to remove balances.
|
|
413
|
+
get().removeBalancesForWallet(walletType, {
|
|
414
|
+
namespaces: requestedNamesapces,
|
|
415
|
+
});
|
|
356
416
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
417
|
+
get()._changeSelectedWalletIfNeededOnRemove(walletType, {
|
|
418
|
+
namespaces: requestedNamesapces,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const nextConnectedWallets = get().connectedWallets.filter(
|
|
422
|
+
(connectedWallet) => {
|
|
423
|
+
if (connectedWallet.namespace) {
|
|
424
|
+
const targetWalletAndNamespace =
|
|
425
|
+
connectedWallet.walletType === walletType &&
|
|
426
|
+
requestedNamesapces.includes(connectedWallet.namespace);
|
|
427
|
+
|
|
428
|
+
// If the wallet and namespace matched, we should filter it out.
|
|
429
|
+
return !targetWalletAndNamespace;
|
|
430
|
+
}
|
|
431
|
+
/*
|
|
432
|
+
* if a connected wallet hasn't `namesapce`, it means it legacy.
|
|
433
|
+
* legacy will not reach this method, but for we check anyways
|
|
434
|
+
*/
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
362
437
|
);
|
|
438
|
+
|
|
439
|
+
set({
|
|
440
|
+
connectedWallets: nextConnectedWallets,
|
|
441
|
+
});
|
|
363
442
|
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
443
|
+
},
|
|
444
|
+
disconnectWallet: (walletType) => {
|
|
445
|
+
const isTargetWalletExistsInConnectedWallets =
|
|
446
|
+
get().connectedWallets.find(
|
|
447
|
+
(wallet) => wallet.walletType === walletType
|
|
448
|
+
);
|
|
449
|
+
/*
|
|
450
|
+
* Previously DISCONNECT event was being emitted if target wallet existed in connected wallets.
|
|
451
|
+
* Considering that connected wallets get clear on namespace disconnect in hub,
|
|
452
|
+
* now emitting this event is done without checking for connected wallets to be compatible with hub.
|
|
453
|
+
*/
|
|
375
454
|
eventEmitter.emit(WidgetEvents.WalletEvent, {
|
|
376
455
|
type: WalletEventTypes.DISCONNECT,
|
|
377
456
|
payload: { walletType },
|
|
378
457
|
});
|
|
458
|
+
if (isTargetWalletExistsInConnectedWallets) {
|
|
459
|
+
// This should be called before updating connectedWallets since we need the old state to remove balances.
|
|
460
|
+
get().removeBalancesForWallet(walletType);
|
|
379
461
|
|
|
380
|
-
|
|
381
|
-
get().removeBalancesForWallet(walletType);
|
|
462
|
+
get()._changeSelectedWalletIfNeededOnRemove(walletType);
|
|
382
463
|
|
|
383
|
-
|
|
384
|
-
.connectedWallets.filter(
|
|
464
|
+
// Remove target wallet from connectedWallets
|
|
465
|
+
const nextConnectedWallets = get().connectedWallets.filter(
|
|
466
|
+
(connectedWallet) => connectedWallet.walletType !== walletType
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
set({
|
|
470
|
+
connectedWallets: nextConnectedWallets,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
/*
|
|
475
|
+
* If we are disconnecting a wallet that has `selected` for some blockchains,
|
|
476
|
+
* For those blockchains we will fallback to first connected wallet
|
|
477
|
+
* which means selected wallet will change.
|
|
478
|
+
*/
|
|
479
|
+
_changeSelectedWalletIfNeededOnRemove: (walletType, options) => {
|
|
480
|
+
let connectedWallets = get().connectedWallets;
|
|
481
|
+
|
|
482
|
+
if (options?.namespaces && options.namespaces.length > 0) {
|
|
483
|
+
connectedWallets = connectedWallets.filter(
|
|
484
|
+
(connectedWallet) =>
|
|
485
|
+
!!connectedWallet.namespace &&
|
|
486
|
+
options.namespaces?.includes(connectedWallet.namespace)
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
let targetWalletWasSelectedForBlockchains = connectedWallets
|
|
491
|
+
.filter(
|
|
385
492
|
(connectedWallet) =>
|
|
386
493
|
connectedWallet.selected &&
|
|
387
494
|
connectedWallet.walletType === walletType
|
|
388
495
|
)
|
|
389
496
|
.map((connectedWallet) => connectedWallet.chain);
|
|
390
497
|
|
|
391
|
-
// Remove target wallet from connectedWallets
|
|
392
|
-
let nextConnectedWallets = get().connectedWallets.filter(
|
|
393
|
-
(connectedWallet) => connectedWallet.walletType !== walletType
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
/*
|
|
397
|
-
* If we are disconnecting a wallet that has `selected` for some blockchains,
|
|
398
|
-
* For those blockchains we will fallback to first connected wallet
|
|
399
|
-
* which means selected wallet will change.
|
|
400
|
-
*/
|
|
401
498
|
if (targetWalletWasSelectedForBlockchains.length > 0) {
|
|
402
|
-
nextConnectedWallets =
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
targetWalletWasSelectedForBlockchains
|
|
410
|
-
(
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
499
|
+
const nextConnectedWallets = get().connectedWallets.map(
|
|
500
|
+
(connectedWallet) => {
|
|
501
|
+
if (
|
|
502
|
+
targetWalletWasSelectedForBlockchains.includes(
|
|
503
|
+
connectedWallet.chain
|
|
504
|
+
)
|
|
505
|
+
) {
|
|
506
|
+
targetWalletWasSelectedForBlockchains =
|
|
507
|
+
targetWalletWasSelectedForBlockchains.filter(
|
|
508
|
+
(blockchain) => blockchain !== connectedWallet.chain
|
|
509
|
+
);
|
|
510
|
+
return {
|
|
511
|
+
...connectedWallet,
|
|
512
|
+
selected: true,
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return connectedWallet;
|
|
416
517
|
}
|
|
518
|
+
);
|
|
417
519
|
|
|
418
|
-
|
|
520
|
+
set({
|
|
521
|
+
connectedWallets: nextConnectedWallets,
|
|
419
522
|
});
|
|
420
523
|
}
|
|
524
|
+
},
|
|
525
|
+
clearConnectedWallet: () => set({ connectedWallets: [] }),
|
|
526
|
+
fetchBalances: async (accounts, options) => {
|
|
527
|
+
// All the `accounts` have same `walletType` so we can pick the first one.
|
|
528
|
+
const walletType = accounts[0].walletType;
|
|
421
529
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
address: account.address,
|
|
436
|
-
blockchain: account.chain,
|
|
437
|
-
}));
|
|
438
|
-
const response = await httpService().getWalletsDetails(addressesToFetch);
|
|
439
|
-
|
|
440
|
-
const walletsDetails = response.wallets;
|
|
441
|
-
|
|
442
|
-
if (walletsDetails) {
|
|
443
|
-
const { retryOnFailedBalances = true } = options || {};
|
|
444
|
-
if (retryOnFailedBalances) {
|
|
445
|
-
const failedWallets: Wallet[] = walletsDetails
|
|
446
|
-
.filter((wallet) => wallet.failed)
|
|
447
|
-
.map((wallet) => ({
|
|
448
|
-
chain: wallet.blockChain,
|
|
449
|
-
walletType: walletType,
|
|
450
|
-
address: wallet.address,
|
|
451
|
-
}));
|
|
452
|
-
if (failedWallets.length > 0) {
|
|
453
|
-
void get().fetchBalances(failedWallets, {
|
|
454
|
-
retryOnFailedBalances: false,
|
|
455
|
-
});
|
|
456
|
-
}
|
|
530
|
+
get().setConnectedWalletAsRefetching(accounts);
|
|
531
|
+
|
|
532
|
+
const addressesToFetch = accounts.map((account) => ({
|
|
533
|
+
address: account.address,
|
|
534
|
+
blockchain: account.chain,
|
|
535
|
+
}));
|
|
536
|
+
|
|
537
|
+
let response;
|
|
538
|
+
try {
|
|
539
|
+
response = await httpService().getWalletsDetails(addressesToFetch);
|
|
540
|
+
} catch (e) {
|
|
541
|
+
get().setConnectedWalletHasError(accounts);
|
|
542
|
+
throw new Error(`Request for fetching balances failed.`, { cause: e });
|
|
457
543
|
}
|
|
458
544
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
if (
|
|
464
|
-
|
|
545
|
+
const walletsDetails = response.wallets;
|
|
546
|
+
|
|
547
|
+
if (walletsDetails) {
|
|
548
|
+
const { retryOnFailedBalances = true } = options || {};
|
|
549
|
+
if (retryOnFailedBalances) {
|
|
550
|
+
const failedWallets: Wallet[] = walletsDetails
|
|
551
|
+
.filter((wallet) => wallet.failed)
|
|
552
|
+
.map((wallet) => ({
|
|
553
|
+
chain: wallet.blockChain,
|
|
554
|
+
walletType: walletType,
|
|
555
|
+
address: wallet.address,
|
|
556
|
+
}));
|
|
557
|
+
if (failedWallets.length > 0) {
|
|
558
|
+
void get().fetchBalances(failedWallets, {
|
|
559
|
+
retryOnFailedBalances: false,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
465
562
|
}
|
|
466
563
|
|
|
467
|
-
|
|
564
|
+
let nextBalances: BalanceState = {};
|
|
565
|
+
let nextAggregatedBalances: AggregatedBalanceState =
|
|
566
|
+
get()._aggregatedBalances;
|
|
567
|
+
walletsDetails.forEach((wallet) => {
|
|
568
|
+
if (wallet.failed) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
468
571
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
572
|
+
// Remove old balances for current wallet and blockchain
|
|
573
|
+
get().removeBalancesForWallet(walletType, {
|
|
574
|
+
chains: [wallet.blockChain],
|
|
575
|
+
});
|
|
473
576
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
577
|
+
/*
|
|
578
|
+
* Check if after fetching balance for an account, the account still exists.
|
|
579
|
+
* (It might get disconnected while fetching balances is pending)
|
|
580
|
+
*/
|
|
581
|
+
if (
|
|
582
|
+
!get().connectedWallets.find(
|
|
583
|
+
(connectedWallet) =>
|
|
584
|
+
connectedWallet.walletType === walletType &&
|
|
585
|
+
connectedWallet.address === wallet.address &&
|
|
586
|
+
connectedWallet.chain === wallet.blockChain
|
|
587
|
+
)
|
|
588
|
+
) {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
479
591
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
},
|
|
485
|
-
_aggregatedBalances: nextAggregatedBalances,
|
|
486
|
-
}));
|
|
592
|
+
const balancesForWallet = createBalanceStateForNewAccount(
|
|
593
|
+
wallet,
|
|
594
|
+
get
|
|
595
|
+
);
|
|
487
596
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
`We couldn't fetch your account balances. Seem there is no information on blockchain for them yet.`
|
|
493
|
-
);
|
|
494
|
-
}
|
|
495
|
-
},
|
|
496
|
-
getBalances: () => {
|
|
497
|
-
return get()._balances;
|
|
498
|
-
},
|
|
499
|
-
getBalanceFor: (token) => {
|
|
500
|
-
const balances = get().getBalances();
|
|
597
|
+
nextAggregatedBalances = updateAggregatedBalanceStateForNewAccount(
|
|
598
|
+
nextAggregatedBalances,
|
|
599
|
+
balancesForWallet
|
|
600
|
+
);
|
|
501
601
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
*/
|
|
602
|
+
nextBalances = {
|
|
603
|
+
...nextBalances,
|
|
604
|
+
...balancesForWallet,
|
|
605
|
+
};
|
|
606
|
+
});
|
|
508
607
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
608
|
+
set((state) => ({
|
|
609
|
+
_balances: {
|
|
610
|
+
...state._balances,
|
|
611
|
+
...nextBalances,
|
|
612
|
+
},
|
|
613
|
+
_aggregatedBalances: nextAggregatedBalances,
|
|
614
|
+
}));
|
|
615
|
+
|
|
616
|
+
get().setConnectedWalletRetrievedData(accounts, walletsDetails);
|
|
617
|
+
} else {
|
|
618
|
+
get().setConnectedWalletHasError(accounts);
|
|
619
|
+
throw new Error(
|
|
620
|
+
`We couldn't fetch your account balances. Seem there is no information on blockchain for them yet.`
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
},
|
|
624
|
+
getBalances: () => {
|
|
625
|
+
return get()._balances;
|
|
626
|
+
},
|
|
627
|
+
getBalanceFor: (token) => {
|
|
628
|
+
const balances = get().getBalances();
|
|
512
629
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
630
|
+
/*
|
|
631
|
+
* The old implementation wasn't considering user's address.
|
|
632
|
+
* it can be problematic when two separate address has same token, both of them will override on same key.
|
|
633
|
+
*
|
|
634
|
+
* For keeping the same behavior, here we pick the most amount and also will not consider user's address in key.
|
|
635
|
+
*/
|
|
519
636
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
targetBalanceKeys.forEach((targetBalanceKey) => {
|
|
524
|
-
const currentBalance = balances[targetBalanceKey];
|
|
525
|
-
const currentBalanceAmount = new BigNumber(currentBalance.amount);
|
|
526
|
-
const prevBalanceAmount = new BigNumber(maxBalance.amount);
|
|
637
|
+
// Note: balance key is created using asset key + wallet address
|
|
638
|
+
const assetKey = createAssetKey(token);
|
|
639
|
+
const targetBalanceKeys = get()._aggregatedBalances[assetKey] || [];
|
|
527
640
|
|
|
528
|
-
if (
|
|
529
|
-
|
|
641
|
+
if (targetBalanceKeys.length === 0) {
|
|
642
|
+
return null;
|
|
643
|
+
} else if (targetBalanceKeys.length === 1) {
|
|
644
|
+
const targetKey = targetBalanceKeys[0];
|
|
645
|
+
return balances[targetKey];
|
|
530
646
|
}
|
|
531
|
-
});
|
|
532
|
-
return maxBalance;
|
|
533
|
-
},
|
|
534
|
-
getBalancesForWalletAddress: (address: string) => {
|
|
535
|
-
const balances = get().getBalances();
|
|
536
|
-
const balanceKeys = Object.keys(balances) as BalanceKey[];
|
|
537
|
-
|
|
538
|
-
const balancesForTargetWalletAddress = balanceKeys.reduce(
|
|
539
|
-
(output, balanceKey) => {
|
|
540
|
-
const balance = balances[balanceKey];
|
|
541
|
-
|
|
542
|
-
const [, , , balanceWalletAddreess] = balanceKey.split('-');
|
|
543
|
-
if (balanceWalletAddreess === address) {
|
|
544
|
-
output[balanceKey] = balance;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
return output;
|
|
548
|
-
},
|
|
549
|
-
{} as BalanceState
|
|
550
|
-
);
|
|
551
|
-
|
|
552
|
-
return balancesForTargetWalletAddress;
|
|
553
|
-
},
|
|
554
|
-
getConnectedWalletsDetails: () => {
|
|
555
|
-
const connectedWallets = get().connectedWallets;
|
|
556
|
-
return connectedWallets.map((wallet) => {
|
|
557
|
-
const balances = get().getBalancesForWalletAddress(wallet.address);
|
|
558
|
-
const balancesKeys = Object.keys(balances) as BalanceKey[];
|
|
559
|
-
|
|
560
|
-
return {
|
|
561
|
-
...wallet,
|
|
562
|
-
balances: balancesKeys.reduce((output, balanceKey) => {
|
|
563
|
-
const balance = balances[balanceKey];
|
|
564
|
-
const asset = extractAssetFromBalanceKey(balanceKey);
|
|
565
647
|
|
|
566
|
-
|
|
567
|
-
|
|
648
|
+
// If there are multiple balances for an specific token, we pick the maximum.
|
|
649
|
+
const firstTargetBalance = balances[targetBalanceKeys[0]];
|
|
650
|
+
let maxBalance: Balance = firstTargetBalance;
|
|
651
|
+
targetBalanceKeys.forEach((targetBalanceKey) => {
|
|
652
|
+
const currentBalance = balances[targetBalanceKey];
|
|
653
|
+
const currentBalanceAmount = new BigNumber(currentBalance.amount);
|
|
654
|
+
const prevBalanceAmount = new BigNumber(maxBalance.amount);
|
|
568
655
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
656
|
+
if (currentBalanceAmount.isGreaterThan(prevBalanceAmount)) {
|
|
657
|
+
maxBalance = currentBalance;
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
return maxBalance;
|
|
661
|
+
},
|
|
662
|
+
getBalancesForWalletAddress: (address: string) => {
|
|
663
|
+
const balances = get().getBalances();
|
|
664
|
+
const balanceKeys = Object.keys(balances) as BalanceKey[];
|
|
665
|
+
|
|
666
|
+
const balancesForTargetWalletAddress = balanceKeys.reduce(
|
|
667
|
+
(output, balanceKey) => {
|
|
668
|
+
const balance = balances[balanceKey];
|
|
572
669
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
address: asset.address,
|
|
578
|
-
rawAmount: balance.amount,
|
|
579
|
-
decimal: balance.decimals,
|
|
580
|
-
amount: amount.toString(),
|
|
581
|
-
logo: token?.image || null,
|
|
582
|
-
usdPrice: token?.usdPrice || null,
|
|
583
|
-
});
|
|
670
|
+
const [, , , balanceWalletAddreess] =
|
|
671
|
+
balanceKey.split(BALANCE_SEPARATOR);
|
|
672
|
+
if (balanceWalletAddreess === address) {
|
|
673
|
+
output[balanceKey] = balance;
|
|
584
674
|
}
|
|
585
675
|
|
|
586
676
|
return output;
|
|
587
|
-
},
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
677
|
+
},
|
|
678
|
+
{} as BalanceState
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
return balancesForTargetWalletAddress;
|
|
682
|
+
},
|
|
683
|
+
getConnectedWalletsDetails: () => {
|
|
684
|
+
return memoizedConnectedWalletsWithNestedBalances(() => {
|
|
685
|
+
const connectedWallets = get().connectedWallets;
|
|
686
|
+
return connectedWallets.map((wallet) => {
|
|
687
|
+
const balances = get().getBalancesForWalletAddress(wallet.address);
|
|
688
|
+
const balancesKeys = Object.keys(balances) as BalanceKey[];
|
|
689
|
+
|
|
690
|
+
return {
|
|
691
|
+
...wallet,
|
|
692
|
+
balances: balancesKeys.reduce((output, balanceKey) => {
|
|
693
|
+
const balance = balances[balanceKey];
|
|
694
|
+
const asset = extractAssetFromBalanceKey(balanceKey);
|
|
695
|
+
|
|
696
|
+
if (asset.blockchain === wallet.chain) {
|
|
697
|
+
const token = get().findToken(asset);
|
|
698
|
+
|
|
699
|
+
const amount = balance.amount
|
|
700
|
+
? new BigNumber(balance.amount).shiftedBy(-balance.decimals)
|
|
701
|
+
: ZERO;
|
|
702
|
+
|
|
703
|
+
output.push({
|
|
704
|
+
chain: wallet.chain,
|
|
705
|
+
symbol: asset.symbol,
|
|
706
|
+
ticker: asset.symbol,
|
|
707
|
+
address: asset.address,
|
|
708
|
+
rawAmount: balance.amount,
|
|
709
|
+
decimal: balance.decimals,
|
|
710
|
+
amount: amount.toString(),
|
|
711
|
+
logo: token?.image || null,
|
|
712
|
+
usdPrice: token?.usdPrice || null,
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return output;
|
|
717
|
+
}, [] as DeprecatedTokenBalance[]),
|
|
718
|
+
};
|
|
719
|
+
});
|
|
720
|
+
}, get().lastUpdatedAt);
|
|
721
|
+
},
|
|
722
|
+
})
|
|
723
|
+
);
|