Skip to content

Commit

Permalink
feat(dw): add receiver account search field
Browse files Browse the repository at this point in the history
  • Loading branch information
javadkh2 committed Dec 2, 2024
1 parent a67011b commit 1b97416
Show file tree
Hide file tree
Showing 25 changed files with 1,063 additions and 400 deletions.
30 changes: 30 additions & 0 deletions packages/apps/dev-wallet/src/App/Layout/useRightAside.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useLayout } from '@kadena/kode-ui/patterns';
import { useEffect, useState } from 'react';

export function useRightAside() {
const [expanded, setExpanded] = useState(false);
const { isRightAsideExpanded, setIsRightAsideExpanded } = useLayout();

useEffect(() => {
if (!isRightAsideExpanded && expanded) {
setExpanded(false);
}
}, [isRightAsideExpanded, expanded]);

return [
expanded,
() => {
if (isRightAsideExpanded && !expanded) {
throw new Error('Right aside is already open with a different panel');
}
setIsRightAsideExpanded(true);
setExpanded(true);
},
() => {
if (expanded) {
setIsRightAsideExpanded(false);
setExpanded(false);
}
},
] as [isExpanded: boolean, expand: () => void, close: () => void];
}
135 changes: 76 additions & 59 deletions packages/apps/dev-wallet/src/Components/AccountInput/AccountInput.tsx
Original file line number Diff line number Diff line change
@@ -1,126 +1,132 @@
import { Keyset } from '@/pages/transfer-v2/Components/keyset';
import { discoverReceiver } from '@/pages/transfer-v2/utils';
import { DiscoverdAccounts } from '@/pages/transfer/components/DiscoverdAccounts';
import { IReceiverAccount } from '@/pages/transfer/utils';
import { discoverReceiver, IReceiverAccount } from '@/pages/transfer-v2/utils';

import {
MonoAccountBalanceWallet,
MonoLoading,
} from '@kadena/kode-icons/system';
import { Button, Notification, Stack, TextField } from '@kadena/kode-ui';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { KeySetDialog } from '../KeysetDialog/KeySetDialog';
import { DiscoverdAccounts } from './DiscoverdAccounts';

export function AccountInput({
networkId,
contract,
onAccount,
account,
address,
setAddress,
}: {
networkId: string;
contract: string;
account?: IReceiverAccount;
onAccount: (account: IReceiverAccount) => void;
account: IReceiverAccount | undefined;
address: string;
setAddress: (address: string) => void;
onAccount: (account?: IReceiverAccount) => void;
}) {
const [address, setAddress] = useState(account?.address || '');
console.log('AccountInput', account);
const [discoveredAccounts, setDiscoveredAccounts] = useState<
IReceiverAccount[]
>([]);
IReceiverAccount[] | undefined
>(undefined);
const [needToAddKeys, setNeedToAddKeys] = useState(false);
const [showKeysetDialog, setShowKeysetDialog] = useState(false);
const [error, setError] = useState<Error | null>(null);
const [discovering, setDiscovering] = useState(false);
const selectedAccount =
discoveredAccounts.length === 1 ? discoveredAccounts[0] : undefined;

useEffect(() => {
if (account?.address) {
setAddress(account.address);
handleDiscover(account.address);
}
}, [account?.address]);
const [discovering, setDiscovering] = useState<string | undefined>(undefined);

const handleDiscover = async (addressArg?: string) => {
console.log('handleDiscover', addressArg, discovering);
const innerAddress = typeof addressArg === 'string' ? addressArg : address;
try {
if (!innerAddress) {
if (
!innerAddress ||
innerAddress === discovering ||
innerAddress === account?.address
) {
return;
}
setDiscovering(true);
setDiscovering(innerAddress);
setNeedToAddKeys(false);
setDiscoveredAccounts(undefined);
onAccount(undefined);
const accounts = await discoverReceiver(
innerAddress,
networkId,
contract,
(key) => key,
);
setDiscovering(false);
if (accounts.length === 1) {
onAccount(accounts[0]);
}
if (accounts.length > 1) {
setDiscoveredAccounts(accounts);
return;
}
if (accounts.length === 0) {
setNeedToAddKeys(true);
return;
}
setDiscoveredAccounts(accounts);
onAccount(accounts[0]);
setDiscovering(undefined);
} catch (e: any) {

Check warning on line 68 in packages/apps/dev-wallet/src/Components/AccountInput/AccountInput.tsx

View workflow job for this annotation

GitHub Actions / Build & unit test

Unexpected any. Specify a different type
setError(e && e.message ? e : JSON.stringify(e));
}
};

return (
<Stack flexDirection={'column'}>
<Stack flexDirection={'column'} gap={'md'}>
{showKeysetDialog && (
<KeySetDialog
close={() => setShowKeysetDialog(false)}
onDone={(guard) => {
setShowKeysetDialog(false);
setNeedToAddKeys(false);
const account: IReceiverAccount = {
address,
address: address,
keyset: { guard },
chains: [],
overallBalance: '0.0',
};
setDiscoveredAccounts([account]);
onAccount(account);
}}
isOpen
/>
)}
{discoveredAccounts.length >= 2 && (
<DiscoverdAccounts
accounts={discoveredAccounts}
onSelect={(account: IReceiverAccount) => {
setDiscoveredAccounts([account]);
onAccount(account);
<Stack flexDirection={'column'}>
<TextField
aria-label="Account"
key={'account-input'}
startVisual={
<Stack gap={'sm'}>
<MonoAccountBalanceWallet />
</Stack>
}
description={
discovering ? (
<Stack>
<MonoLoading /> Discovering...
</Stack>
) : (
error?.message
)
}
value={address}
onChange={(e) => {
const newAddress = e.target.value;
setAddress(newAddress);
if (account && newAddress !== account?.address) {
onAccount(undefined);
}
}}
autoFocus={false}
onFocusChange={(isFocused) => {
if (!isFocused && !account) {
console.log('onBlur called', address);
handleDiscover(address);
}
}}
/>
)}
<TextField
aria-label="Account"
startVisual={
<Stack gap={'sm'}>
<MonoAccountBalanceWallet />
</Stack>
}
description={
discovering ? (
<Stack>
<MonoLoading /> Discovering...
</Stack>
) : (
error?.message
)
}
value={address}
onChange={(e) => setAddress(e.target.value)}
onBlur={() => handleDiscover()}
/>
{selectedAccount && selectedAccount.keyset.guard && (
<Keyset guard={selectedAccount.keyset.guard} />
)}
{account && account.keyset.guard && (
<Keyset guard={account.keyset.guard} />
)}
</Stack>
{needToAddKeys && (
<Notification role="status" intent="info">
The address is not recognized. Please add the public key to the
Expand All @@ -136,6 +142,17 @@ export function AccountInput({
</Stack>
</Notification>
)}
{discoveredAccounts && discoveredAccounts.length >= 2 && (
<DiscoverdAccounts
accounts={discoveredAccounts}
onSelect={(account: IReceiverAccount) => {
setDiscoveredAccounts(undefined);
onAccount(account);
}}
onClosed={() => setDiscoveredAccounts(undefined)}
inline
/>
)}
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Keyset } from '@/pages/transfer-v2/Components/keyset';
import { IReceiverAccount } from '@/pages/transfer-v2/utils';
import { MonoAttachMoney, MonoLink } from '@kadena/kode-icons/system';
import {
Button,
Dialog,
DialogContent,
DialogHeader,
Stack,
Text,
} from '@kadena/kode-ui';
import { FC, ReactNode } from 'react';
import { discoverdAccountClass } from './style.css';

export const DiscoverdAccounts: FC<{
accounts: IReceiverAccount[];
onSelect: (selected: IReceiverAccount) => void;
onClosed: () => void;
inline?: boolean;
}> = ({ accounts, onSelect, onClosed, inline }) => {
const Wrapper = ({ children }: { children: ReactNode }) => {
if (inline) {
return <Stack gap={'sm'}>{children}</Stack>;
}
return (
<Dialog
size="sm"
isOpen={accounts.length > 0}
onOpenChange={(isOpen) => {
if (!isOpen) {
onClosed();
}
}}
>
{children}
</Dialog>
);
};

return (
<Wrapper>
{!inline && <DialogHeader>Select the receiver account</DialogHeader>}
<DialogContent>
<Stack flexDirection={'column'} gap={'sm'}>
<Text>
There are {accounts.length} accounts associated with the same
address on the Blockchain. Please select the account you want to
use.
</Text>
<Text>Address: {accounts[0].address}</Text>
<Stack flexDirection={'column'}>
{accounts.map((account) => (
<Stack
gap={'sm'}
alignItems={'center'}
className={discoverdAccountClass}
justifyContent={'space-between'}
>
<Stack
gap={inline ? undefined : 'sm'}
flexDirection={inline ? 'column' : 'row'}
flex={1}
>
<Text size="smallest" color="emphasize">
<Stack gap={'xs'} alignItems={'center'}>
<MonoAttachMoney />
{account.overallBalance}
</Stack>
</Text>
<Text size="smallest" color="emphasize">
<Stack gap={'xs'} alignItems={'center'}>
<MonoLink /> (
{account.chains.map(({ chainId }) => chainId).join(',')})
</Stack>
</Text>
</Stack>
<Stack
gap={'sm'}
justifyContent={'flex-end'}
alignItems={'center'}
>
<Keyset guard={account.keyset.guard} />
<Stack>
<Button
isCompact
variant="outlined"
onPress={() => onSelect(account)}
>
Select
</Button>
</Stack>
</Stack>
</Stack>
))}
</Stack>
</Stack>
</DialogContent>
</Wrapper>
);
};
16 changes: 16 additions & 0 deletions packages/apps/dev-wallet/src/Components/AccountInput/style.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { atoms, vars } from '@kadena/kode-ui/styles';
import { style } from '@vanilla-extract/css';

export const discoverdAccountClass = style([
{
backgroundColor: vars.colors.$layoutSurfaceCard,
selectors: {
'&:nth-child(odd)': {
backgroundColor: vars.colors.$layoutSurfaceDefault,
},
},
},
atoms({
padding: 'sm',
}),
]);
Loading

0 comments on commit 1b97416

Please sign in to comment.