Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: web wallet composite #236

Closed
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8842243
feat: web wallet composite
leonardocbsr Sep 2, 2024
9333ef7
feature: components
leonardocbsr Sep 2, 2024
4222f76
feat: webwallet component
leonardocbsr Sep 5, 2024
79c9b97
chore: dark mode support
leonardocbsr Sep 6, 2024
5c7a4e7
chore: prevent auto focus
leonardocbsr Sep 6, 2024
5ffc446
chore: webwallet as a opt-in feat
leonardocbsr Sep 6, 2024
4a11ca8
Merge branch 'main' into feature/web-wallet-composite
leocourbassier Sep 6, 2024
ae0a86f
chore: make the webwallet look like fuels wallet
leonardocbsr Sep 6, 2024
d8f982e
chore: a few tweaks to the wallet
leonardocbsr Sep 6, 2024
f120616
doc: update changeset
leonardocbsr Sep 6, 2024
eaa5bb2
chore: refetch everything if connected again
leonardocbsr Sep 6, 2024
7efff84
chore: styles update
leonardocbsr Sep 13, 2024
1ceb2af
fix: change @fuels/ui package location
leonardocbsr Sep 13, 2024
137aea9
chore: update variant to outline
leonardocbsr Sep 13, 2024
593e681
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Sep 13, 2024
c86683d
chore: a few tweaks to web wallet & cleanup
leonardocbsr Sep 18, 2024
10172a8
chore: bump @fuels/ui
leonardocbsr Sep 21, 2024
d3e6f82
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Sep 21, 2024
7cf7357
chore: add fuels
leonardocbsr Sep 21, 2024
e021a8f
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Sep 24, 2024
6c71f5e
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Sep 25, 2024
738ecd0
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Sep 26, 2024
804fbde
chore: reconcile with main branch
leonardocbsr Sep 26, 2024
1908271
Merge branch 'main' into feature/web-wallet-composite
leocourbassier Sep 26, 2024
8c7f51c
Merge branch 'main' into feature/web-wallet-composite
leocourbassier Sep 27, 2024
bb3c092
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Sep 30, 2024
40de6f0
chore: reconcile with main branch
leonardocbsr Sep 30, 2024
ac4a2eb
Merge branch 'main' into feature/web-wallet-composite
leocourbassier Sep 30, 2024
8977940
Merge remote-tracking branch 'upstream/main' into feature/web-wallet-…
leonardocbsr Oct 1, 2024
a7366ff
chore: reconcile with main branch
leonardocbsr Oct 1, 2024
2d9a237
Merge branch 'main' into feature/web-wallet-composite
leocourbassier Oct 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/poor-beers-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuels/react": minor
---

Added a component "WebWallet" to increase UX when using connectors
5 changes: 4 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,18 @@
},
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"@types/react": "18.3.1",
"@tabler/icons-react": "2.47.0",
"events": "^3.3.0"
},
"devDependencies": {
"@fuels/ui": "0.0.1",
"@tanstack/react-query": "5.35.1",
"@types/react": "18.2.54",
"compare-versions": "^6.1.0",
"fuels": "0.93.0",
"react": "^18.2.0",
"styled-components": "^6.1.1",
"tailwindcss": "3.4.4",
"tsup": "^7.2.0",
"tsx": "4.9.3",
"typescript": "5.4.5"
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/providers/FuelProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { FuelConfig } from 'fuels';

import { Connect } from '../ui/Connect';

import { WebWallet } from '../ui/WebWallet';
import { FuelHooksProvider } from './FuelHooksProvider';
import { FuelUIProvider, type FuelUIProviderProps } from './FuelUIProvider';

Expand All @@ -24,6 +25,7 @@ export function FuelProvider({
<FuelHooksProvider fuelConfig={fuelConfig}>
<FuelUIProvider theme={theme} fuelConfig={fuelConfig}>
<Connect />
<WebWallet />
leonardocbsr marked this conversation as resolved.
Show resolved Hide resolved
{children}
</FuelUIProvider>
</FuelHooksProvider>
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/providers/FuelUIProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { useConnect } from '../hooks/useConnect';
import { useConnectors } from '../hooks/useConnectors';

import { Theme, type ThemeProps } from '@fuels/ui';
import { useFuel } from './FuelHooksProvider';

export type FuelUIProviderProps = {
Expand Down Expand Up @@ -132,7 +133,7 @@ export function FuelUIProvider({
},
}}
>
{children}
<Theme hasBackground={false}>{children}</Theme>
</FuelConnectContext.Provider>
);
}
36 changes: 36 additions & 0 deletions packages/react/src/ui/WebWallet/components/Anchor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Button, Popover } from '@fuels/ui';
import { IconWallet } from '@tabler/icons-react';
import React from 'react';

export interface IAnchorProps {
address: string;
onClick?: () => void;
isLoading: boolean;
isConnected: boolean;
}

const AnchorComponent = (
{ address, onClick, isLoading, isConnected }: IAnchorProps,
ref: React.ForwardedRef<HTMLButtonElement> | null,
) => {
return (
<Button
variant="solid"
radius="full"
onClick={onClick}
leftIcon={IconWallet}
size={'2'}
isLoading={isLoading && isConnected}
disabled={!isConnected}
ref={ref}
style={{
backgroundColor: 'grey',
}}
highContrast
>
{address && isConnected ? address : 'Connect your wallet'}
</Button>
);
};

export const Anchor = React.forwardRef(AnchorComponent);
54 changes: 54 additions & 0 deletions packages/react/src/ui/WebWallet/components/Assets/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Heading, Table, Text, Tooltip, VStack } from '@fuels/ui';
import type { CoinQuantity } from 'fuels';
import { StyledColumnHeaderCell, StyledText } from './styles';

export interface IAssetsProps {
assets: CoinQuantity[];
}

export const Assets = ({ assets }: IAssetsProps) => {
return (
<VStack gap="3">
<Text size="3" weight="medium">
Assets
</Text>
<Table className="w-full" variant="ghost" size="1">
<Table.Header>
<Table.Row>
<StyledColumnHeaderCell topLeft>
<Text size="1" weight="medium" className="pl-3">
Token
</Text>
</StyledColumnHeaderCell>
<StyledColumnHeaderCell topRight>
<Text size="1" weight="medium">
Price
</Text>
</StyledColumnHeaderCell>
</Table.Row>
</Table.Header>

<Table.Body>
{assets.map((asset) => {
return (
<Table.Row key={asset.assetId}>
<Table.RowHeaderCell>
<Tooltip content={asset.assetId}>
<StyledText size="1" className="pl-3">
{asset.assetId}
</StyledText>
</Tooltip>
</Table.RowHeaderCell>
<Table.Cell>
<Tooltip content={asset.amount.format()}>
<StyledText size="1">{asset.amount.format()}</StyledText>
</Tooltip>
</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table>
</VStack>
);
};
26 changes: 26 additions & 0 deletions packages/react/src/ui/WebWallet/components/Assets/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Table, type TableColumnHeaderCell, Text } from '@fuels/ui';
import styled from 'styled-components';

export interface StyledColumnHeaderCellProps {
topLeft?: boolean;
topRight?: boolean;
}
export const StyledColumnHeaderCell = styled<
typeof TableColumnHeaderCell,
StyledColumnHeaderCellProps
>(Table.ColumnHeaderCell)`
background-color: var(--gray-3);
border-radius: ${(props) => {
const t = props.topLeft ? 0.75 : 0;
const r = props.topRight ? 0.75 : 0;
return `${t}rem ${r}rem 0 0`;
}};
`;

export const StyledText = styled(Text)`
display: block;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 120px;
`;
17 changes: 17 additions & 0 deletions packages/react/src/ui/WebWallet/components/Balance/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Card, Heading, LoadingBox, Text, VStack } from '@fuels/ui';

export interface IBalanceProps {
value: string | null;
}
export const Balance = ({ value }: IBalanceProps) => {
return (
<Card className="max-w-xl">
<VStack gap="0">
<Text color="gray" size="1">
Total Balance
</Text>
<Heading size="6">{value} ETH</Heading>
</VStack>
</Card>
);
};
3 changes: 3 additions & 0 deletions packages/react/src/ui/WebWallet/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './Anchor';
export * from './Balance';
export * from './Assets';
127 changes: 127 additions & 0 deletions packages/react/src/ui/WebWallet/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import {
Button,
EntityItem,
EntityItemInfo,
HStack,
Heading,
Popover,
Separator,
VStack,
shortAddress,
} from '@fuels/ui';
import { type BN, type CoinQuantity, bn } from 'fuels';
import { useEffect, useState } from 'react';
import {
useAccount,
useDisconnect,
useIsConnected,
useWallet,
} from '../../hooks';
import { Anchor, Assets, Balance } from './components';
import { Overlay } from './styles';
import '@fuels/ui/styles.css';
import { IconHistory, IconLogout } from '@tabler/icons-react';

export const WebWallet = () => {
const [address, setAddress] = useState('');
const [balance, setBalance] = useState('');
const [assetsBalances, setAssetsBalances] = useState<CoinQuantity[]>([]);

const { account, isFetched: isFetchedAccount } = useAccount();
const { isConnected } = useIsConnected();
const { disconnect } = useDisconnect();
const { wallet, isFetched: isFetchedWallet } = useWallet();

const disconnectWallet = () => {
disconnect();
};

useEffect(() => {
if (!isConnected) {
setAddress('');
setBalance('');
setAssetsBalances([]);
}
}, [isConnected]);

useEffect(() => {
if (isFetchedWallet && wallet) {
wallet
.getBalances()
.then(({ balances }) => {
setAssetsBalances(balances);
})
.catch(console.error);
}
}, [wallet, isFetchedWallet]);

useEffect(() => {
if (assetsBalances.length > 0) {
const balance = assetsBalances
.reduce((acc: BN, { amount }) => {
return acc.add(amount ?? bn(0));
}, bn(0))
.format();
setBalance(balance);
}
}, [assetsBalances]);

useEffect(() => {
if (isFetchedAccount && account) {
setAddress(account);
}
}, [account, isFetchedAccount]);

const isLoading = !isFetchedAccount || !isFetchedWallet || balance === '';

return (
<Overlay>
<Popover className="mr-4 rounded-md right-12 bottom-12">
<Popover.Trigger>
<Anchor
address={shortAddress(address)}
isLoading={isLoading}
isConnected={isConnected}
/>
</Popover.Trigger>
<Popover.Content side="top" sticky="always">
<VStack gap="3" minHeight={{ md: '400px', xl: '400px' }}>
<EntityItem>
<EntityItemInfo id={address} title="Your Wallet" />
</EntityItem>
<Balance value={balance} />
<Separator size="4" />
<Assets assets={assetsBalances} />

<Popover.Close>
<HStack mt="auto" justify="end" gap="1">
<Button
as="a"
href={`https://app.fuel.network/account/${address}/transactions`}
target="_blank"
rel="noreferrer"
variant="outline"
size="1"
leftIcon={IconHistory}
radius="full"
>
History
</Button>
<Button
color="red"
variant="outline"
size="1"
leftIcon={IconLogout}
radius="full"
onClick={() => disconnectWallet()}
>
Disconnect
</Button>
</HStack>
</Popover.Close>
</VStack>
</Popover.Content>
</Popover>
</Overlay>
);
};
7 changes: 7 additions & 0 deletions packages/react/src/ui/WebWallet/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { styled } from 'styled-components';

export const Overlay = styled.div`
position: fixed;
bottom: 50px;
right: 50px;
`;
5 changes: 5 additions & 0 deletions packages/react/src/ui/WebWallet/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface IAssetsBalance {
token: string;
name: string;
price: string;
}
1 change: 1 addition & 0 deletions packages/react/tsup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export default defineConfig((options) => ({
minify: true,
clean: true,
entry: ['src/index.ts'],
external: ['@fuels/ui'],
}));
Loading
Loading