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(bridge-ui-v2): review step #14940

Merged
merged 25 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9268817
Squashed commit of the following:
KorbinianK Oct 2, 2023
f984245
detectContract update and test
KorbinianK Oct 2, 2023
d83bc54
tokenInfo
KorbinianK Oct 2, 2023
3f60b87
check ownership
KorbinianK Oct 4, 2023
21c4664
fix error for detectContractType
KorbinianK Oct 4, 2023
ad26dbf
test for getTokenInfo
KorbinianK Oct 4, 2023
f129e4a
tokeninfo, form reset, processing fee and recipient
KorbinianK Oct 4, 2023
8047687
fixes
KorbinianK Oct 4, 2023
50e573d
Merge branch 'main' into feat/bridge-ui-v2--nft-import-step
KorbinianK Oct 4, 2023
51ba505
fetching from eventIndexer
KorbinianK Oct 5, 2023
61e3c4d
todo texts
KorbinianK Oct 5, 2023
a8426f9
basic layout setup and icons
KorbinianK Oct 5, 2023
fa7c78b
safeReadContract util
KorbinianK Oct 9, 2023
6f09461
getTokenWithInfo util
KorbinianK Oct 9, 2023
ba27a4a
fetch from API, dummy image
KorbinianK Oct 9, 2023
6b7610d
Merge remote-tracking branch 'origin/main' into feat/bridge-ui-v2--nf…
KorbinianK Oct 9, 2023
c92a0ae
env fix
KorbinianK Oct 9, 2023
3558dc5
Merge remote-tracking branch 'origin/feat/bridge-ui-v2--nft-import-ap…
KorbinianK Oct 10, 2023
12f1bde
group nfts by collection
KorbinianK Oct 10, 2023
7e2213d
icon flipper
KorbinianK Oct 11, 2023
00414e3
nft utils
KorbinianK Oct 11, 2023
f2cef64
display nft as cards or list
KorbinianK Oct 11, 2023
6bdd345
i18n stuff
KorbinianK Oct 11, 2023
6cfa15c
alert changes
KorbinianK Oct 11, 2023
77f8215
Merge remote-tracking branch 'origin/main' into feat/bridge-ui-v2--re…
KorbinianK Oct 11, 2023
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
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
node_modules
/build
/.svelte-kit
.svelte-kit/
/package
.env
.env.*
Expand Down
167 changes: 136 additions & 31 deletions packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
import { Button } from '$components/Button';
import { Card } from '$components/Card';
import { ChainSelectorWrapper } from '$components/ChainSelector';
import ChainSelector from '$components/ChainSelector/ChainSelector.svelte';
import { Icon } from '$components/Icon';
import IconFlipper from '$components/Icon/IconFlipper.svelte';
import { NFTCard } from '$components/NFTCard';
import { NFTList } from '$components/NFTList';
import { successToast, warningToast } from '$components/NotificationToast';
import { errorToast, infoToast } from '$components/NotificationToast/NotificationToast.svelte';
Expand Down Expand Up @@ -40,6 +44,7 @@
import { getTokenWithInfoFromAddress } from '$libs/token/getTokenWithInfoFromAddress';
import { refreshUserBalance } from '$libs/util/balance';
import { getConnectedWallet } from '$libs/util/getConnectedWallet';
import { shortenAddress } from '$libs/util/shortenAddress';
import { type Account, account } from '$stores/account';
import { type Network, network } from '$stores/network';
import { pendingTransactions } from '$stores/pendingTransactions';
Expand Down Expand Up @@ -364,6 +369,7 @@

let nftStepTitle: string;
let nftStepDescription: string;
let nextStepButtonText: string;
let nftIdArray: number[];
let enteredIds: string = '';
let contractAddress: Address | '';
Expand All @@ -381,6 +387,12 @@
let foundNFTs: NFT[] = [];
let selectedNFT: NFT[] = [];

enum NFTView {
CARDS,
LIST,
}
let nftView: NFTView = NFTView.CARDS;

function onAddressValidation(event: CustomEvent<{ isValidEthereumAddress: boolean; addr: Address }>) {
const { isValidEthereumAddress, addr } = event.detail;
addressInputState = AddressInputState.Validating;
Expand All @@ -406,6 +418,7 @@
addressInputState = AddressInputState.Invalid;
}
}

const scanForNFTs = async () => {
scanning = true;
const accountAddress = $account?.address;
Expand All @@ -417,8 +430,27 @@
scanned = true;
};

const changeNFTView = () => {
if (nftView === NFTView.CARDS) {
nftView = NFTView.LIST;
} else {
nftView = NFTView.CARDS;
}
};

const searchNFTs = () => {
// TODO: implement
};

// Whenever the user switches bridge types, we should reset the forms
$: $activeBridge && resetForm();
$: $activeBridge && (resetForm(), (activeStep = NFTSteps.IMPORT));

$: {
const stepKey = NFTSteps[activeStep].toLowerCase();
nftStepTitle = $t(`bridge.title.nft.${stepKey}`);
nftStepDescription = $t(`bridge.description.nft.${stepKey}`);
nextStepButtonText = activeStep === NFTSteps.CONFIRM ? $t('common.confirm') : $t('common.continue');
}

$: {
const stepKey = NFTSteps[activeStep].toLowerCase();
Expand Down Expand Up @@ -545,54 +577,126 @@
Automatic NFT Input
-->
<div class="f-between-center w-full gap-4">
<Button
disabled={!canScan}
loading={scanning}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={scanForNFTs}>Scan for NFTs</Button>
{#if !scanned}
<Button
disabled={!canScan}
loading={scanning}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={scanForNFTs}>{$t('bridge.actions.nft_scan')}</Button>
{:else}
<Button
disabled={!canScan}
loading={scanning}
type="neutral"
class="px-[28px] py-[14px] rounded-full flex-1 bg-transparent !border border-primary-brand hover:border-primary-interactive-hover"
on:click={scanForNFTs}>{$t('bridge.actions.nft_scan_again')}</Button>
{/if}
</div>

<!--
Automatic NFT Input
-->
<div class="f-col w-full gap-4">
{#if scanned}
<h2>Your NFTs:</h2>
<h2>{$t('bridge.nft.step.import.scan_screen.title')}</h2>
<!-- Todo: also enable card view here? -->
<NFTList bind:nfts={foundNFTs} chainId={$network?.id} bind:selectedNFT />

<div class="flex items-center justify-between space-x-2">
<span class="text-sm">Don't see your NFTs?<br /> Try adding them manually!</span>
<FlatAlert type="warning" message={$t('bridge.nft.step.import.scan_screen.description')} />
<Button
type="neutral"
class="bg-transparent !border border-primary-brand hover:border-primary-interactive-hover py-[14px]"
class="bg-transparent !border border-primary-brand hover:border-primary-interactive-hover "
on:click={() => (manualNFTInput = !manualNFTInput)}>
Add manually
{$t('bridge.actions.nft_manual')}
</Button>
</div>
{/if}

<NFTList bind:nfts={foundNFTs} chainId={$network?.id} bind:selectedNFT />
</div>
{/if}

<!-- REVIEW STEP -->
{:else if activeStep === NFTSteps.REVIEW}
<div class="container mx-auto inline-block align-middle space-y-[25px]">
<div class="flex justify-between mb-2 items-center">
<div class="font-bold">{$t('common.destination')}</div>
<div><ChainSelector small value={$destinationChain} readOnly /></div>
</div>

<div class="flex justify-between mb-2">
<div class="font-bold">{$t('common.contract_address')}</div>
<div class="text-secondary-content">
<ul>
{#each selectedNFT as nft}
{@const currentChain = $network?.id}
{#if currentChain && $destinationChain?.id}
<li>
<a
class="flex justify-start link"
href={`${chainConfig[$destinationChain?.id].urls.explorer}`}
target="_blank">
{shortenAddress(nft.addresses[currentChain], 8, 12)}
<Icon type="arrow-top-right" fillClass="fill-primary-link" />
</a>
</li>
{/if}
{/each}
</ul>
</div>
</div>

<div class="flex justify-between">
<div class="font-bold">{$t('bridge.nft.step.review.token_id')}</div>
<div class="break-words text-right text-secondary-content">
<ul>
{#each selectedNFT as nft}
<li>{nft.tokenId}</li>
{/each}
</ul>
</div>
</div>
</div>
<div class="h-sep" />
<!--
Recipient & Processing Fee
-->
<div class="space-y-[16px]">
<Recipient bind:this={recipientComponent} />
<ProcessingFee bind:this={processingFeeComponent} />
</div>
<!-- REVIEW STEP -->
{:else if activeStep === NFTSteps.REVIEW}
<div class="f-between-center gap-4">
<div class="f-col">
<p>Contract: {contractAddress}</p>
<div class="h-sep" />
<div class="flex justify-between items-center w-full">
<div class="flex items-center gap-2">
<span>{$t('bridge.nft.step.review.your_tokens')}</span>
<ChainSelector small value={$network} readOnly />
</div>
<div class="flex gap-2">
<Button
disabled={true}
shape="circle"
type="neutral"
class="!w-9 !h-9 rounded-full"
on:click={searchNFTs}>
<Icon type="magnifier" fillClass="fill-primary-icon" size={24} vWidth={24} vHeight={24} />
</Button>
<IconFlipper
iconType1="list"
iconType2="cards"
selectedDefault="list"
class="bg-neutral w-9 h-9 rounded-full"
on:labelclick={changeNFTView} />
<!-- <Icon type="list" fillClass="fill-primary-icon" size={24} vWidth={24} vHeight={24} /> -->
</div>
</div>
{#if nftView === NFTView.LIST}
<NFTList bind:nfts={selectedNFT} chainId={$network?.id} viewOnly />
{:else if nftView === NFTView.CARDS}
<div class="rounded-[20px] bg-neutral min-h-[200px] w-full p-2 f-center">
{#each selectedNFT as nft}
<p>Name: {nft.name}</p>
<p>Type: {nft.type}</p>
<p>ID: {nft.tokenId}</p>
<p>URI: {nft.uri}</p>
<p>Balance: {nft.balance}</p>
<NFTCard {nft} />
{/each}

<!-- <p>IDs: {nftIdArray.join(', ')}</p> -->
</div>
</div>
{/if}
<!-- CONFIRM STEP -->
{:else if activeStep === NFTSteps.CONFIRM}
<div class="f-between-center gap-4">
Expand All @@ -607,15 +711,16 @@
<div class="f-between-center w-full gap-4">
{#if activeStep !== NFTSteps.IMPORT}
<Button
type="secondary"
class="px-[28px] py-[14px] rounded-full flex-1 text-secondary-content"
on:click={previousStep}>Previous Step</Button>
type="neutral"
class="px-[28px] py-[14px] rounded-full w-auto flex-1 bg-transparent !border border-primary-brand hover:border-primary-interactive-hover"
on:click={previousStep}>
<span class="body-bold">{$t('common.edit')}</span></Button>
{/if}
<Button
disabled={!canProceed}
type="primary"
class="px-[28px] py-[14px] rounded-full flex-1 text-white"
on:click={nextStep}>Next Step</Button>
on:click={nextStep}><span class="body-bold">{nextStepButtonText}</span></Button>
</div>
</div></Card>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
'flex justify-start content-center',
);

let iconSize = small ? 'w-5 h-5' : 'w-7 h-7';

let switchingNetwork = false;
let buttonId = `button-${uid()}`;
let dialogId = `dialog-${uid()}`;
Expand Down Expand Up @@ -134,7 +136,7 @@
{#if value}
{@const icon = chainConfig[Number(value.id)]?.icon || 'Unknown Chain'}
<i role="img" aria-label={value.name}>
<img src={icon} alt="chain-logo" class="rounded-full w-6 h-6" />
<img src={icon} alt="chain-logo" class="rounded-full {iconSize}" />
</i>
<span>{truncateString(value.name, 8)}</span>
{/if}
Expand Down
28 changes: 25 additions & 3 deletions packages/bridge-ui-v2/src/components/Icon/Icon.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
| 'trash'
| 'adjustments'
| 'sun'
| 'moon';
| 'moon'
| 'list'
| 'magnifier'
| 'cards';
</script>

<script lang="ts">
Expand Down Expand Up @@ -226,6 +229,25 @@
class={fillClass}
fill="none"
d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"
></path
>{/if}
></path>
{:else if type === 'list'}
<path
class={fillClass}
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.375 6.75C3.375 6.12868 3.87868 5.625 4.5 5.625C5.12132 5.625 5.625 6.12868 5.625 6.75C5.625 7.37132 5.12132 7.875 4.5 7.875C3.87868 7.875 3.375 7.37132 3.375 6.75ZM8.25 6.75C8.25 6.33579 8.58579 6 9 6H21C21.4142 6 21.75 6.33579 21.75 6.75C21.75 7.16421 21.4142 7.5 21 7.5H9C8.58579 7.5 8.25 7.16421 8.25 6.75ZM3.375 12C3.375 11.3787 3.87868 10.875 4.5 10.875C5.12132 10.875 5.625 11.3787 5.625 12C5.625 12.6213 5.12132 13.125 4.5 13.125C3.87868 13.125 3.375 12.6213 3.375 12ZM8.25 12C8.25 11.5858 8.58579 11.25 9 11.25H21C21.4142 11.25 21.75 11.5858 21.75 12C21.75 12.4142 21.4142 12.75 21 12.75H9C8.58579 12.75 8.25 12.4142 8.25 12ZM3.375 17.25C3.375 16.6287 3.87868 16.125 4.5 16.125C5.12132 16.125 5.625 16.6287 5.625 17.25C5.625 17.8713 5.12132 18.375 4.5 18.375C3.87868 18.375 3.375 17.8713 3.375 17.25ZM8.25 17.25C8.25 16.8358 8.58579 16.5 9 16.5H21C21.4142 16.5 21.75 16.8358 21.75 17.25C21.75 17.6642 21.4142 18 21 18H9C8.58579 18 8.25 17.6642 8.25 17.25Z"
fill="none" />
{:else if type === 'cards'}
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="2" y="2" width="12" height="12" />
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="18" y="2" width="12" height="12" />
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="2" y="18" width="12" height="12" />
<rect class={fillClass} fill-rule="evenodd" clip-rule="evenodd" x="18" y="18" width="12" height="12" />
{:else if type === 'magnifier'}
<path
class={fillClass}
fill-rule="evenodd"
clip-rule="evenodd"
d="M19.5151 9.54126C19.5151 6.05828 16.6915 3.23477 13.2086 3.23477C9.72559 3.23477 6.90208 6.05828 6.90208 9.54126C6.90208 11.2829 7.60719 12.8586 8.74921 14.0006C9.89123 15.1426 11.4669 15.8478 13.2086 15.8478C16.6915 15.8478 19.5151 13.0242 19.5151 9.54126ZM13.2086 1.83333C17.4655 1.83333 20.9165 5.28429 20.9165 9.54126C20.9165 13.7982 17.4655 17.2492 13.2086 17.2492C11.3327 17.2492 9.61242 16.5783 8.27618 15.4646L3.89396 19.8468C3.62031 20.1205 3.17664 20.1205 2.90299 19.8468C2.62934 19.5732 2.62934 19.1295 2.90299 18.8559L7.28521 14.4737C6.17148 13.1374 5.50064 11.4172 5.50064 9.54126C5.50064 5.28429 8.9516 1.83333 13.2086 1.83333Z"
fill="none" />
{/if}
</svg>
28 changes: 28 additions & 0 deletions packages/bridge-ui-v2/src/components/Icon/IconFlipper.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';

import { Icon, type IconType } from '$components/Icon';
import { classNames } from '$libs/util/classNames';

export let iconType1: IconType;
export let iconType2: IconType;

export let selectedDefault: IconType = iconType1;

const dispatch = createEventDispatcher();

function handleLabelClick() {
selectedDefault = selectedDefault === iconType1 ? iconType2 : iconType1;
dispatch('labelclick');
}

$: isDefault = selectedDefault === iconType1;

$: classes = classNames('swap swap-rotate', $$props.class);
</script>

<div role="button" tabindex="0" class={classes} on:click={handleLabelClick} on:keypress={handleLabelClick}>
<input type="checkbox" class="border-none" bind:checked={isDefault} />
<Icon type={iconType1} class="fill-primary-icon swap-on" width={25} height={25} vHeight={25} vWidth={25} />
<Icon type={iconType2} class="fill-primary-icon swap-off" width={25} height={25} vHeight={25} vWidth={25} />
</div>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/Icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export { default as BllIcon } from './BLL.svelte';
export { default as EthIcon } from './ETH.svelte';
export { default as HorseIcon } from './HORSE.svelte';
export { default as Icon, type IconType } from './Icon.svelte';
export { default as IconFlipper } from './IconFlipper.svelte';
export { default as TTKOIcon } from './TTKO.svelte';
Loading
Loading