-
Notifications
You must be signed in to change notification settings - Fork 17
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(tangle-dapp): Bridge UI on Tangle Dapp #2307
Merged
Merged
Changes from 6 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
38c5017
feat: add new Bridge page and prepare the UI
vutuanlinh2k2 5c01cf8
chore: handle select chain
vutuanlinh2k2 bf344bf
chore: handle connect wallet
vutuanlinh2k2 f76852f
chore: switch chain button
vutuanlinh2k2 21aed34
chore: add comments
vutuanlinh2k2 43cf7a6
chore: add more comments
vutuanlinh2k2 f395aad
chore: update chain selector logic
vutuanlinh2k2 4041770
feat: add token selection dropdown
vutuanlinh2k2 1d0086b
chore: update dropdown size
vutuanlinh2k2 d0cec21
fix: update Component name to fix CI
vutuanlinh2k2 49ba508
chore: format code
vutuanlinh2k2 45a9d9a
chore: fix CI
vutuanlinh2k2 5ccf758
chore: merge with devleop
vutuanlinh2k2 a632d35
chore: UI update
vutuanlinh2k2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
'use client'; | ||
|
||
import Button from '@webb-tools/webb-ui-components/components/buttons/Button'; | ||
import { FC } from 'react'; | ||
import { twMerge } from 'tailwind-merge'; | ||
|
||
import AddressInput, { | ||
AddressType, | ||
} from '../../components/AddressInput/AddressInput'; | ||
import AmountInput from '../../components/AmountInput/AmountInput'; | ||
import { useBridge } from '../../context/BridgeContext'; | ||
import ChainSelectors from './ChainSelectors'; | ||
import useActionButton from './useActionButton'; | ||
|
||
interface BridgeContainerProps { | ||
className?: string; | ||
} | ||
|
||
const BridgeContainer: FC<BridgeContainerProps> = ({ className }) => { | ||
const { destinationAddress, setDestinationAddress, amount, setAmount } = | ||
useBridge(); | ||
const { buttonAction, buttonText, isLoading } = useActionButton(); | ||
|
||
return ( | ||
<div | ||
className={twMerge( | ||
'max-w-[640px] min-h-[580px] bg-mono-0 dark:bg-mono-190 p-8', | ||
'rounded-xl border border-mono-40 dark:border-mono-160', | ||
'shadow-webb-lg dark:shadow-webb-lg-dark', | ||
'flex flex-col', | ||
className | ||
)} | ||
> | ||
<div className="flex-1 w-full flex flex-col justify-between"> | ||
<div className="space-y-8"> | ||
<ChainSelectors /> | ||
|
||
<AmountInput | ||
id="bridge-amount-input" | ||
title="Amount" | ||
amount={amount} | ||
setAmount={setAmount} | ||
baseInputOverrides={{ | ||
isFullWidth: true, | ||
}} | ||
placeholder="" | ||
/> | ||
|
||
<AddressInput | ||
id="bridge-destination-address-input" | ||
type={AddressType.Both} | ||
title="Receiver Address" | ||
baseInputOverrides={{ isFullWidth: true }} | ||
value={destinationAddress} | ||
setValue={setDestinationAddress} | ||
/> | ||
|
||
{/* TODO: Tx Info (Fees & Estimated Time) */} | ||
</div> | ||
<Button | ||
isFullWidth | ||
isDisabled={isLoading} | ||
isLoading={isLoading} | ||
onClick={buttonAction} | ||
loadingText="Connecting..." | ||
> | ||
{buttonText} | ||
</Button> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default BridgeContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
'use client'; | ||
|
||
import { DropdownMenuTrigger as DropdownTrigger } from '@radix-ui/react-dropdown-menu'; | ||
import { ChainConfig } from '@webb-tools/dapp-config/chains/chain-config.interface'; | ||
import { ArrowRight } from '@webb-tools/icons/ArrowRight'; | ||
import { ChainIcon } from '@webb-tools/icons/ChainIcon'; | ||
import ChainButton from '@webb-tools/webb-ui-components/components/buttons/ChainButton'; | ||
import { | ||
Dropdown, | ||
DropdownBody, | ||
} from '@webb-tools/webb-ui-components/components/Dropdown'; | ||
import { MenuItem } from '@webb-tools/webb-ui-components/components/MenuItem'; | ||
import { ScrollArea } from '@webb-tools/webb-ui-components/components/ScrollArea'; | ||
import { FC, useCallback } from 'react'; | ||
|
||
import { useBridge } from '../../context/BridgeContext'; | ||
|
||
interface ChainSelectorProps { | ||
title: string; | ||
selectedChain: ChainConfig | null; | ||
chainOptions: ChainConfig[]; | ||
onSelectChain: (chain: ChainConfig) => void; | ||
className?: string; | ||
} | ||
|
||
const ChainSelectors: FC = () => { | ||
const { | ||
sourceChain, | ||
setSourceChain, | ||
destinationChain, | ||
setDestinationChain, | ||
supportedSourceChains, | ||
supportedDestinationChains, | ||
} = useBridge(); | ||
|
||
const onSetSourceChain = useCallback( | ||
(chain: ChainConfig) => { | ||
setSourceChain(chain); | ||
// If the source chain is the same as the destination chain, clear the destination chain. | ||
if (chain.id === destinationChain?.id) { | ||
setDestinationChain(null); | ||
} | ||
}, | ||
[destinationChain?.id, setDestinationChain, setSourceChain] | ||
); | ||
|
||
const onSetDestinationChain = useCallback( | ||
(chain: ChainConfig) => { | ||
setDestinationChain(chain); | ||
// If the destination chain is the same as the source chain, clear the source chain. | ||
if (chain.id === sourceChain?.id) { | ||
setSourceChain(null); | ||
} | ||
}, | ||
[setDestinationChain, setSourceChain, sourceChain?.id] | ||
); | ||
|
||
const switchChains = useCallback(() => { | ||
const temp = sourceChain; | ||
|
||
// If the destination chain is null or is in the supported destination chains, | ||
// set it as the source chain. | ||
if ( | ||
temp === null || | ||
supportedDestinationChains.find((chain) => chain.id === temp.id) | ||
) { | ||
setDestinationChain(temp); | ||
} else { | ||
setDestinationChain(null); | ||
} | ||
|
||
// If the source chain is null or is in the supported source chains, | ||
// set it as the destination chain. | ||
if ( | ||
destinationChain === null || | ||
supportedSourceChains.find((chain) => chain.id === destinationChain.id) | ||
) { | ||
setSourceChain(destinationChain); | ||
} else { | ||
setSourceChain(null); | ||
} | ||
}, [ | ||
setSourceChain, | ||
setDestinationChain, | ||
destinationChain, | ||
sourceChain, | ||
supportedDestinationChains, | ||
supportedSourceChains, | ||
]); | ||
|
||
return ( | ||
<div className="flex flex-col md:flex-row justify-between items-center gap-3"> | ||
<ChainSelector | ||
title="From" | ||
selectedChain={sourceChain} | ||
chainOptions={supportedSourceChains} | ||
onSelectChain={onSetSourceChain} | ||
className="flex-1 w-full md:w-auto" | ||
/> | ||
|
||
<div | ||
className="cursor-pointer p-1 rounded-full hover:bg-mono-20 dark:hover:bg-mono-160" | ||
onClick={switchChains} | ||
> | ||
<ArrowRight size="lg" className="rotate-90 md:rotate-0" /> | ||
</div> | ||
|
||
<ChainSelector | ||
title="To" | ||
selectedChain={destinationChain} | ||
chainOptions={supportedDestinationChains} | ||
onSelectChain={onSetDestinationChain} | ||
className="flex-1 w-full md:w-auto" | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
const ChainSelector: FC<ChainSelectorProps> = ({ | ||
title, | ||
selectedChain, | ||
chainOptions, | ||
onSelectChain, | ||
className, | ||
}) => { | ||
return ( | ||
<Dropdown className={className}> | ||
<DropdownTrigger asChild> | ||
<ChainButton | ||
chain={selectedChain ?? undefined} | ||
status="success" | ||
placeholder={selectedChain === null ? title : undefined} | ||
className="w-full bg-mono-20 dark:bg-mono-160 border-0" | ||
textClassName={ | ||
selectedChain === null ? 'text-mono-100 dark:text-mono-80' : '' | ||
} | ||
/> | ||
</DropdownTrigger> | ||
<DropdownBody> | ||
<ScrollArea className="max-h-[300px]"> | ||
<ul> | ||
{chainOptions.map((chain) => { | ||
return ( | ||
<li key={`${chain.chainType}-${chain.id}`}> | ||
<MenuItem | ||
startIcon={<ChainIcon size="lg" name={chain.name} />} | ||
onSelect={() => onSelectChain(chain)} | ||
> | ||
{chain.name} | ||
</MenuItem> | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
</ScrollArea> | ||
</DropdownBody> | ||
</Dropdown> | ||
); | ||
}; | ||
|
||
export default ChainSelectors; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { FC, PropsWithChildren } from 'react'; | ||
|
||
import BridgeProvider from '../../context/BridgeContext'; | ||
|
||
const BridgeLayout: FC<PropsWithChildren> = ({ children }) => { | ||
return <BridgeProvider>{children}</BridgeProvider>; | ||
}; | ||
|
||
export default BridgeLayout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { Metadata } from 'next'; | ||
import { FC } from 'react'; | ||
|
||
import createPageMetadata from '../../utils/createPageMetadata'; | ||
import BridgeContainer from './BridgeContainer'; | ||
|
||
export const metadata: Metadata = createPageMetadata({ | ||
title: 'Bridge', | ||
}); | ||
|
||
const Bridge: FC = () => { | ||
return ( | ||
<div> | ||
<BridgeContainer className="mx-auto" /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Bridge; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use client'; | ||
|
||
import { | ||
useConnectWallet, | ||
useWebContext, | ||
} from '@webb-tools/api-provider-environment'; | ||
import { useCallback, useMemo } from 'react'; | ||
|
||
export default function useActionButton() { | ||
const { activeAccount, activeWallet, loading, isConnecting } = | ||
useWebContext(); | ||
|
||
const { toggleModal } = useConnectWallet(); | ||
|
||
const noActiveAccountOrWallet = useMemo(() => { | ||
return !activeAccount || !activeWallet; | ||
}, [activeAccount, activeWallet]); | ||
|
||
const openWalletModal = useCallback(() => { | ||
toggleModal(true); | ||
}, [toggleModal]); | ||
|
||
const bridgeTx = useCallback(() => { | ||
// TODO: handle bridge Tx for each case from the source and destination chain | ||
}, []); | ||
|
||
return { | ||
isLoading: loading || isConnecting, | ||
buttonAction: noActiveAccountOrWallet ? openWalletModal : bridgeTx, | ||
buttonText: noActiveAccountOrWallet ? 'Connect' : 'Transfer', | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { chainsConfig } from '@webb-tools/dapp-config'; | ||
import { ChainConfig } from '@webb-tools/dapp-config/chains/chain-config.interface'; | ||
import { PresetTypedChainId } from '@webb-tools/dapp-types'; | ||
|
||
// This is just a temporary variable to use as supported source and destination chains | ||
export const BRIDGE_SUPPORTED_CHAINS: ChainConfig[] = [ | ||
chainsConfig[PresetTypedChainId.TangleMainnetNative], | ||
chainsConfig[PresetTypedChainId.TangleTestnetNative], | ||
]; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that instead of switching and nullifying things that we should not present the same chain as an option? Or do you think this is better. I'm ambivalent is this is the logic you think is worth having.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working on it right now!