@rango-dev/ui 0.13.0 → 0.13.1-next.0

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 (60) hide show
  1. package/dist/index.js +6 -6
  2. package/dist/index.js.map +4 -4
  3. package/dist/widget/ui/src/components/HeaderLayout/HeaderLayout.d.ts +14 -0
  4. package/dist/widget/ui/src/components/HeaderLayout/HeaderLayout.d.ts.map +1 -0
  5. package/dist/widget/ui/src/components/HeaderLayout/index.d.ts +2 -0
  6. package/dist/widget/ui/src/components/HeaderLayout/index.d.ts.map +1 -0
  7. package/dist/widget/ui/src/components/PercentageChange/PercentageChange.d.ts +8 -0
  8. package/dist/widget/ui/src/components/PercentageChange/PercentageChange.d.ts.map +1 -0
  9. package/dist/widget/ui/src/components/PercentageChange/index.d.ts +2 -0
  10. package/dist/widget/ui/src/components/PercentageChange/index.d.ts.map +1 -0
  11. package/dist/widget/ui/src/components/RoutesOverview/RoutesOverview.d.ts +120 -0
  12. package/dist/widget/ui/src/components/RoutesOverview/RoutesOverview.d.ts.map +1 -0
  13. package/dist/widget/ui/src/components/RoutesOverview/index.d.ts +2 -0
  14. package/dist/widget/ui/src/components/RoutesOverview/index.d.ts.map +1 -0
  15. package/dist/widget/ui/src/components/SwapDetailsPlaceholder/SwapDetailsPlaceholder.d.ts +120 -0
  16. package/dist/widget/ui/src/components/SwapDetailsPlaceholder/SwapDetailsPlaceholder.d.ts.map +1 -0
  17. package/dist/widget/ui/src/components/SwapDetailsPlaceholder/index.d.ts +2 -0
  18. package/dist/widget/ui/src/components/SwapDetailsPlaceholder/index.d.ts.map +1 -0
  19. package/dist/widget/ui/src/components/TokenPreview/TokenPreview.d.ts +20 -0
  20. package/dist/widget/ui/src/components/TokenPreview/TokenPreview.d.ts.map +1 -0
  21. package/dist/widget/ui/src/components/TokenPreview/index.d.ts +2 -0
  22. package/dist/widget/ui/src/components/TokenPreview/index.d.ts.map +1 -0
  23. package/dist/widget/ui/src/components/index.d.ts +5 -0
  24. package/dist/widget/ui/src/components/index.d.ts.map +1 -1
  25. package/dist/widget/ui/src/containers/ConfirmSwap/ConfirmSwap.stories.d.ts.map +1 -1
  26. package/dist/widget/ui/src/containers/HomePanel/HomePanel.d.ts +47 -0
  27. package/dist/widget/ui/src/containers/HomePanel/HomePanel.d.ts.map +1 -0
  28. package/dist/widget/ui/src/containers/HomePanel/index.d.ts +2 -0
  29. package/dist/widget/ui/src/containers/HomePanel/index.d.ts.map +1 -0
  30. package/dist/widget/ui/src/containers/TokenInfo/TokenInfo.d.ts +34 -0
  31. package/dist/widget/ui/src/containers/TokenInfo/TokenInfo.d.ts.map +1 -0
  32. package/dist/widget/ui/src/containers/TokenInfo/index.d.ts +2 -0
  33. package/dist/widget/ui/src/containers/TokenInfo/index.d.ts.map +1 -0
  34. package/dist/widget/ui/src/containers/index.d.ts +2 -0
  35. package/dist/widget/ui/src/containers/index.d.ts.map +1 -1
  36. package/dist/widget/ui/src/types/meta.d.ts +7 -0
  37. package/dist/widget/ui/src/types/meta.d.ts.map +1 -1
  38. package/dist/widget/ui/src/types/wallet.d.ts +23 -0
  39. package/dist/widget/ui/src/types/wallet.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/src/components/HeaderLayout/HeaderLayout.tsx +88 -0
  42. package/src/components/HeaderLayout/index.ts +1 -0
  43. package/src/components/PercentageChange/PercentageChange.tsx +21 -0
  44. package/src/components/PercentageChange/index.ts +1 -0
  45. package/src/components/RoutesOverview/RoutesOverview.tsx +56 -0
  46. package/src/components/RoutesOverview/index.ts +1 -0
  47. package/src/components/SwapDetailsPlaceholder/SwapDetailsPlaceholder.tsx +47 -0
  48. package/src/components/SwapDetailsPlaceholder/index.ts +1 -0
  49. package/src/components/TokenPreview/TokenPreview.tsx +183 -0
  50. package/src/components/TokenPreview/index.ts +1 -0
  51. package/src/components/index.ts +5 -0
  52. package/src/containers/ConfirmSwap/ConfirmSwap.stories.tsx +5 -174
  53. package/src/containers/HomePanel/HomePanel.tsx +228 -0
  54. package/src/containers/HomePanel/index.ts +1 -0
  55. package/src/containers/TokenInfo/TokenInfo.tsx +308 -0
  56. package/src/containers/TokenInfo/index.ts +1 -0
  57. package/src/containers/index.ts +2 -0
  58. package/src/helper/index.ts +1 -1
  59. package/src/types/meta.ts +9 -0
  60. package/src/types/wallet.ts +25 -0
@@ -0,0 +1,228 @@
1
+ import {
2
+ Alert,
3
+ BestRoute,
4
+ BottomLogo,
5
+ Button,
6
+ styled,
7
+ Typography,
8
+ Header,
9
+ HeaderButtons,
10
+ TokenInfo,
11
+ ConnectedWallet,
12
+ } from '../..';
13
+ import React from 'react';
14
+ import { i18n } from '@lingui/core';
15
+ import { BestRouteResponse, BlockchainMeta, SwapResult } from 'rango-sdk';
16
+ import { LoadingStatus, TokenWithBalance } from '../../types/meta';
17
+
18
+ const Container = styled('div', {
19
+ display: 'flex',
20
+ flexDirection: 'column',
21
+ });
22
+
23
+ const FromContainer = styled('div', {
24
+ position: 'relative',
25
+ paddingBottom: '$12',
26
+ });
27
+
28
+ const BestRouteContainer = styled('div', {
29
+ width: '100%',
30
+ paddingTop: '$16',
31
+ });
32
+
33
+ const Alerts = styled('div', {
34
+ width: '100%',
35
+ paddingTop: '$16',
36
+ });
37
+
38
+ const Footer = styled('div', {
39
+ display: 'flex',
40
+ flexDirection: 'column',
41
+ width: '100%',
42
+ paddingTop: '$16',
43
+ });
44
+
45
+ interface HomePanelProps {
46
+ bestRoute: BestRouteResponse | null;
47
+ bestRouteError: string;
48
+ fetchBestRoute: () => void;
49
+ onClickHistory: () => void;
50
+ onClickSettings: () => void;
51
+ fromChain: BlockchainMeta | null;
52
+ toChain: BlockchainMeta | null;
53
+ fromToken: TokenWithBalance | null;
54
+ toToken: TokenWithBalance | null;
55
+ setInputAmount: (amount: string) => void;
56
+ outputAmount: string;
57
+ outputUsdValue: string;
58
+ inputUsdValue: string;
59
+ inputAmount: string;
60
+ loadingStatus: LoadingStatus;
61
+ showBestRoute: boolean;
62
+ fetchingBestRoute: boolean;
63
+ swapButtonTitle: string;
64
+ swapButtonDisabled: boolean;
65
+ swapButtonClick: () => void;
66
+ onChainClick: (route: 'from-chain' | 'to-chain') => void;
67
+ onTokenClick: (route: 'from-token' | 'to-token') => void;
68
+ connectedWallets: ConnectedWallet[];
69
+ highFee: boolean;
70
+ errorMessage: string;
71
+ hasLimitError: (bestRoute: BestRouteResponse | null) => boolean;
72
+ swap: SwapResult | null;
73
+ swapFromAmount: string | null;
74
+ fromAmountRangeError: string;
75
+ recommendation: string;
76
+ totalFeeInUsd: string;
77
+ swithFromAndToComponent: React.ReactNode;
78
+ percentageChange: string;
79
+ tokenBalanceReal: string;
80
+ tokenBalance: string;
81
+ totalTime: string;
82
+ bestRouteData: BestRouteResponse | null;
83
+ showPercentageChange: boolean;
84
+ }
85
+
86
+ export function HomePanel({
87
+ bestRoute,
88
+ bestRouteError,
89
+ fetchBestRoute,
90
+ onClickHistory,
91
+ onClickSettings,
92
+ fromChain,
93
+ toChain,
94
+ fromToken,
95
+ toToken,
96
+ setInputAmount,
97
+ outputAmount,
98
+ inputAmount,
99
+ loadingStatus,
100
+ showBestRoute,
101
+ fetchingBestRoute,
102
+ outputUsdValue,
103
+ inputUsdValue,
104
+ swapButtonTitle,
105
+ swapButtonDisabled,
106
+ swapButtonClick,
107
+ onChainClick,
108
+ onTokenClick,
109
+ connectedWallets,
110
+ highFee,
111
+ errorMessage,
112
+ hasLimitError,
113
+ swap,
114
+ fromAmountRangeError,
115
+ recommendation,
116
+ totalFeeInUsd,
117
+ swithFromAndToComponent,
118
+ percentageChange,
119
+ tokenBalanceReal,
120
+ tokenBalance,
121
+ totalTime,
122
+ bestRouteData,
123
+ swapFromAmount,
124
+ showPercentageChange,
125
+ }: HomePanelProps) {
126
+ return (
127
+ <Container>
128
+ <Header
129
+ title={i18n.t('SWAP')}
130
+ suffix={
131
+ <HeaderButtons
132
+ onClickRefresh={
133
+ !!bestRoute || bestRouteError ? fetchBestRoute : undefined
134
+ }
135
+ onClickHistory={onClickHistory}
136
+ onClickSettings={onClickSettings}
137
+ />
138
+ }
139
+ />
140
+ <FromContainer>
141
+ <>
142
+ <TokenInfo
143
+ type="From"
144
+ chain={fromChain}
145
+ token={fromToken}
146
+ onAmountChange={setInputAmount}
147
+ inputAmount={inputAmount}
148
+ fromChain={fromChain}
149
+ toChain={toChain}
150
+ loadingStatus={loadingStatus}
151
+ inputUsdValue={inputUsdValue}
152
+ fromToken={fromToken}
153
+ setInputAmount={setInputAmount}
154
+ connectedWallets={connectedWallets}
155
+ bestRoute={bestRoute}
156
+ fetchingBestRoute={fetchingBestRoute}
157
+ onChainClick={() => onChainClick('from-chain')}
158
+ onTokenClick={() => onTokenClick('from-token')}
159
+ tokenBalanceReal={tokenBalanceReal}
160
+ tokenBalance={tokenBalance}
161
+ />
162
+ {swithFromAndToComponent}
163
+ </>
164
+ </FromContainer>
165
+ <TokenInfo
166
+ type="To"
167
+ chain={toChain}
168
+ token={toToken}
169
+ outputAmount={outputAmount}
170
+ percentageChange={percentageChange}
171
+ outputUsdValue={outputUsdValue}
172
+ fromChain={fromChain}
173
+ toChain={toChain}
174
+ loadingStatus={loadingStatus}
175
+ inputUsdValue={inputUsdValue}
176
+ fromToken={fromToken}
177
+ setInputAmount={setInputAmount}
178
+ connectedWallets={connectedWallets}
179
+ inputAmount={inputAmount}
180
+ bestRoute={bestRoute}
181
+ fetchingBestRoute={fetchingBestRoute}
182
+ onChainClick={() => onChainClick('to-chain')}
183
+ onTokenClick={() => onTokenClick('to-token')}
184
+ tokenBalanceReal={tokenBalanceReal}
185
+ tokenBalance={tokenBalance}
186
+ showPercentageChange={showPercentageChange}
187
+ />
188
+ {showBestRoute && (
189
+ <BestRouteContainer>
190
+ <BestRoute
191
+ error={bestRouteError}
192
+ loading={fetchingBestRoute}
193
+ data={bestRouteData}
194
+ totalFee={totalFeeInUsd}
195
+ feeWarning={highFee}
196
+ totalTime={totalTime}
197
+ />
198
+ </BestRouteContainer>
199
+ )}
200
+ {(errorMessage || hasLimitError(bestRoute)) && (
201
+ <Alerts>
202
+ {errorMessage && <Alert type="error">{errorMessage}</Alert>}
203
+ {hasLimitError(bestRoute) && (
204
+ <Alert type="error" title={`${swap?.swapperId} Limit`}>
205
+ <>
206
+ <Typography variant="body2">
207
+ {`${fromAmountRangeError}, Yours: ${swapFromAmount} ${swap?.from.symbol}`}
208
+ </Typography>
209
+ <Typography variant="body2">{recommendation}</Typography>
210
+ </>
211
+ </Alert>
212
+ )}
213
+ </Alerts>
214
+ )}
215
+ <Footer>
216
+ <Button
217
+ type="primary"
218
+ align="grow"
219
+ size="large"
220
+ disabled={swapButtonDisabled}
221
+ onClick={swapButtonClick}>
222
+ {swapButtonTitle}
223
+ </Button>
224
+ <BottomLogo />
225
+ </Footer>
226
+ </Container>
227
+ );
228
+ }
@@ -0,0 +1 @@
1
+ export { HomePanel } from './HomePanel';
@@ -0,0 +1,308 @@
1
+ import React from 'react';
2
+ import {
3
+ AngleDownIcon,
4
+ Button,
5
+ InfoCircleIcon,
6
+ styled,
7
+ TextField,
8
+ Typography,
9
+ Image,
10
+ Divider,
11
+ PercentageChange,
12
+ ConnectedWallet,
13
+ } from '../..';
14
+ import { BestRouteResponse, BlockchainMeta, Token } from 'rango-sdk';
15
+ import { Trans } from '@lingui/react';
16
+ import { i18n } from '@lingui/core';
17
+ import { TokenWithBalance } from '../../types/meta';
18
+
19
+ type PropTypes = (
20
+ | {
21
+ type: 'From';
22
+ onAmountChange: (amount: string) => void;
23
+ }
24
+ | {
25
+ type: 'To';
26
+ outputAmount: string;
27
+ outputUsdValue: string;
28
+ percentageChange: string;
29
+ showPercentageChange: boolean;
30
+ }
31
+ ) & {
32
+ chain: BlockchainMeta | null;
33
+ token: Token | null;
34
+ loadingStatus: 'loading' | 'success' | 'failed';
35
+ fromChain: BlockchainMeta | null;
36
+ toChain: BlockchainMeta | null;
37
+ inputUsdValue: string;
38
+ fromToken: TokenWithBalance | null;
39
+ setInputAmount: (amount: string) => void;
40
+ connectedWallets: ConnectedWallet[];
41
+ inputAmount: string;
42
+ bestRoute: BestRouteResponse | null;
43
+ fetchingBestRoute: boolean;
44
+ onChainClick: () => void;
45
+ onTokenClick: () => void;
46
+ tokenBalanceReal: string;
47
+ tokenBalance: string;
48
+ };
49
+
50
+ const Box = styled('div', {
51
+ display: 'flex',
52
+ flexDirection: 'column',
53
+ width: '100%',
54
+ overflow: 'hidden',
55
+ });
56
+
57
+ const Container = styled('div', {
58
+ boxSizing: 'border-box',
59
+ borderRadius: '$5',
60
+ padding: '$8 $16 $16 $16',
61
+
62
+ variants: {
63
+ type: {
64
+ filled: {
65
+ backgroundColor: '$neutral100',
66
+ },
67
+ outlined: {
68
+ border: '1px solid $neutral100',
69
+ backgroundColor: '$surface',
70
+ },
71
+ },
72
+ },
73
+
74
+ defaultVariants: {
75
+ type: 'filled',
76
+ },
77
+
78
+ '.head': {
79
+ display: 'flex',
80
+ justifyContent: 'space-between',
81
+ alignItems: 'center',
82
+ minHeight: '32px',
83
+ },
84
+ '.form': {
85
+ display: 'flex',
86
+ width: '100%',
87
+ padding: '$2 0',
88
+ '.selectors': {
89
+ width: '35%',
90
+
91
+ '._text': {
92
+ whiteSpace: 'nowrap',
93
+ overflow: 'hidden',
94
+ textOverflow: 'ellipsis',
95
+ },
96
+ },
97
+ '.amount': {
98
+ width: '30%',
99
+ },
100
+ },
101
+ '.output-usd': {
102
+ display: 'flex',
103
+ div: {
104
+ display: 'flex',
105
+ paddingLeft: '$8',
106
+ },
107
+ },
108
+ });
109
+
110
+ const Options = styled('div', {
111
+ display: 'flex',
112
+ justifyContent: 'flex-end',
113
+
114
+ '.balance': {
115
+ display: 'flex',
116
+ alignItems: 'center',
117
+ },
118
+ });
119
+
120
+ const ImagePlaceholder = styled('span', {
121
+ width: '24px',
122
+ height: '24px',
123
+ backgroundColor: '$neutral100',
124
+ borderRadius: '99999px',
125
+ });
126
+
127
+ const OutputContainer = styled('div', {
128
+ windth: '100%',
129
+ height: '$48',
130
+ borderRadius: '$5',
131
+ backgroundColor: '$surface',
132
+ border: '1px solid transparent',
133
+ position: 'relative',
134
+ display: 'flex',
135
+ alignItems: 'center',
136
+ paddingLeft: '$8',
137
+ paddingRight: '$8',
138
+ });
139
+
140
+ export function TokenInfo(props: PropTypes) {
141
+ const {
142
+ type,
143
+ chain,
144
+ token,
145
+ loadingStatus,
146
+ fromChain,
147
+ toChain,
148
+ fromToken,
149
+ setInputAmount,
150
+ inputUsdValue,
151
+ inputAmount,
152
+ bestRoute,
153
+ fetchingBestRoute,
154
+ onChainClick,
155
+ onTokenClick,
156
+ tokenBalanceReal,
157
+ tokenBalance,
158
+ } = props;
159
+
160
+ const ItemSuffix = (
161
+ <div
162
+ style={{
163
+ display: 'flex',
164
+ justifyContent: 'center',
165
+ alignItems: 'center',
166
+ }}>
167
+ {loadingStatus === 'failed' && <InfoCircleIcon color="error" size={24} />}
168
+ <AngleDownIcon />
169
+ </div>
170
+ );
171
+
172
+ return (
173
+ <Box>
174
+ <Container type={type === 'From' ? 'filled' : 'outlined'}>
175
+ <div className="head">
176
+ <Typography variant="body2" color="neutral800">
177
+ {type === 'From' ? (
178
+ <Trans id="swap from" message="From" />
179
+ ) : (
180
+ <Trans id="swap to" message="To" />
181
+ )}
182
+ </Typography>
183
+ {type === 'From' ? (
184
+ <Options>
185
+ <div
186
+ className="balance"
187
+ onClick={() => {
188
+ if (tokenBalance !== '0')
189
+ setInputAmount(tokenBalanceReal.split(',').join(''));
190
+ }}>
191
+ <Typography variant="body3" color="neutral600">
192
+ {i18n.t('Balance')}: {tokenBalance} {fromToken?.symbol || ''}
193
+ </Typography>
194
+ <Divider size={4} />
195
+ <Button type="primary" variant="ghost" size="compact">
196
+ <Trans id="maximum amount of asset" message="Max" />
197
+ </Button>
198
+ </div>
199
+ </Options>
200
+ ) : (
201
+ <div className="output-usd">
202
+ <PercentageChange
203
+ percentageChange={props.percentageChange}
204
+ showPercentageChange={props.showPercentageChange}
205
+ />
206
+ <div>
207
+ <Typography
208
+ variant="caption"
209
+ color="neutral600">{`$${props.outputUsdValue}`}</Typography>
210
+ </div>
211
+ </div>
212
+ )}
213
+ </div>
214
+ <div className="form">
215
+ <Button
216
+ className="selectors"
217
+ onClick={onChainClick}
218
+ variant="outlined"
219
+ disabled={loadingStatus === 'failed'}
220
+ loading={loadingStatus === 'loading'}
221
+ prefix={
222
+ loadingStatus === 'success' && chain ? (
223
+ <Image src={chain.logo} size={24} />
224
+ ) : (
225
+ <ImagePlaceholder />
226
+ )
227
+ }
228
+ suffix={ItemSuffix}
229
+ align="start"
230
+ size="large">
231
+ {loadingStatus === 'success' && chain
232
+ ? chain.displayName
233
+ : i18n.t('Chain')}
234
+ </Button>
235
+ <Divider size={12} direction="horizontal" />
236
+ <Button
237
+ className="selectors"
238
+ onClick={onTokenClick}
239
+ variant="outlined"
240
+ disabled={
241
+ loadingStatus === 'failed' ||
242
+ (type === 'From' && !fromChain) ||
243
+ (type === 'To' && !toChain)
244
+ }
245
+ loading={loadingStatus === 'loading'}
246
+ prefix={
247
+ loadingStatus === 'success' && token ? (
248
+ <Image src={token.image} size={24} />
249
+ ) : (
250
+ <ImagePlaceholder />
251
+ )
252
+ }
253
+ suffix={ItemSuffix}
254
+ size="large"
255
+ align="start">
256
+ {loadingStatus === 'success' && token
257
+ ? token.symbol
258
+ : i18n.t('Token')}
259
+ </Button>
260
+ <Divider size={12} direction="horizontal" />
261
+ <div className="amount">
262
+ {type === 'From' ? (
263
+ <TextField
264
+ type="number"
265
+ size="large"
266
+ autoFocus
267
+ placeholder="0"
268
+ style={{
269
+ position: 'relative',
270
+ backgroundColor: '$background !important',
271
+ }}
272
+ suffix={
273
+ <span
274
+ style={{
275
+ position: 'absolute',
276
+ right: '4px',
277
+ bottom: '2px',
278
+ }}>
279
+ <Typography
280
+ variant="caption"
281
+ color="neutral800">{`$${inputUsdValue}`}</Typography>
282
+ </span>
283
+ }
284
+ value={inputAmount || ''}
285
+ min={0}
286
+ onChange={
287
+ type === 'From'
288
+ ? (event) => {
289
+ props.onAmountChange(event.target.value);
290
+ }
291
+ : undefined
292
+ }
293
+ />
294
+ ) : (
295
+ <OutputContainer>
296
+ <Typography variant="h4">
297
+ {fetchingBestRoute && '?'}
298
+ {!!bestRoute?.result && `≈ ${props.outputAmount}`}
299
+ {(!inputAmount || inputAmount === '0') && '0'}
300
+ </Typography>
301
+ </OutputContainer>
302
+ )}
303
+ </div>
304
+ </div>
305
+ </Container>
306
+ </Box>
307
+ );
308
+ }
@@ -0,0 +1 @@
1
+ export { TokenInfo } from './TokenInfo';
@@ -1,9 +1,11 @@
1
1
  export * from './ConfirmSwap';
2
2
  export * from './History';
3
+ export * from './HomePanel';
3
4
  export * from './SwapHistory';
4
5
  export * from './BlockchainSelector';
5
6
  export * from './ConnectWalletsModal';
6
7
  export * from './LiquiditySourcesSelector';
8
+ export * from './TokenInfo';
7
9
  export * from './TokenSelector';
8
10
  export * from './Settings';
9
11
  export * from './Warnings';
@@ -73,7 +73,7 @@ const colorShade = (col: string, amt: number) => {
73
73
  export const generateRangeColors = (
74
74
  name: string,
75
75
  mode: 'light' | 'dark',
76
- color?: string,
76
+ color?: string
77
77
  ) => {
78
78
  let colors = { [name]: color };
79
79
  if (color) {
package/src/types/meta.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Token } from 'rango-sdk';
2
+
1
3
  export type TokenMeta = {
2
4
  blockchain: string;
3
5
  symbol: string;
@@ -20,3 +22,10 @@ export interface LiquiditySource {
20
22
  }
21
23
 
22
24
  export type LoadingStatus = 'loading' | 'success' | 'failed';
25
+
26
+ export interface TokenWithBalance extends Token {
27
+ balance?: {
28
+ amount: string;
29
+ usdValue: string;
30
+ };
31
+ }
@@ -28,3 +28,28 @@ export interface SelectableWallet {
28
28
  selected: boolean;
29
29
  name: string;
30
30
  }
31
+
32
+ interface Wallet {
33
+ chain: string;
34
+ address: string;
35
+ walletType: WalletType;
36
+ }
37
+
38
+ export type TokenBalance = {
39
+ chain: string;
40
+ symbol: string;
41
+ ticker: string;
42
+ address: string | null;
43
+ rawAmount: string;
44
+ decimal: number | null;
45
+ amount: string;
46
+ logo: string | null;
47
+ usdPrice: number | null;
48
+ };
49
+
50
+ export interface ConnectedWallet extends Wallet {
51
+ balances: TokenBalance[] | null;
52
+ loading: boolean;
53
+ error: boolean;
54
+ explorerUrl: string | null;
55
+ }