Skip to content

Commit

Permalink
feat: adds multichain support in Buy/Sell view (#2725)
Browse files Browse the repository at this point in the history
* feat: adds multichain support in BuySell view

* refactor: use network id on transak cryptocurrency

Co-authored-by: Jean Ribeiro <[email protected]>

* use id in token popup filter

* enable buy sell on all profiles

* add network into transak crypto currencies

* dynamically pull in transak cryptos based of profile networks

* enhancment: sort transak cryptos

---------

Co-authored-by: Nicole O'Brien <[email protected]>
  • Loading branch information
jeeanribeiro and nicole-obrien committed Jul 18, 2024
1 parent 055483c commit dbe60be
Show file tree
Hide file tree
Showing 19 changed files with 341 additions and 74 deletions.
2 changes: 2 additions & 0 deletions packages/desktop/components/popup/Popup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import SyncAccountsPopup from './popups/SyncAccountsPopup.svelte'
import TestDeepLinkFormPopup from './popups/TestDeepLinkFormPopup.svelte'
import TokenInformationPopup from './popups/TokenInformationPopup.svelte'
import TransakSelectTokenPopup from './popups/TransakSelectTokenPopup.svelte'
import VoteForProposal from './popups/VoteForProposalPopup.svelte'
import VotingPowerToZeroPopup from './popups/VotingPowerToZeroPopup.svelte'
import { localize } from '@core/i18n'
Expand Down Expand Up @@ -146,6 +147,7 @@
[PopupId.SyncAccounts]: SyncAccountsPopup,
[PopupId.TestDeepLinkForm]: TestDeepLinkFormPopup,
[PopupId.TokenInformation]: TokenInformationPopup,
[PopupId.TransakSelectToken]: TransakSelectTokenPopup,
[PopupId.VoteForProposal]: VoteForProposal,
[PopupId.VotingPowerToZero]: VotingPowerToZeroPopup,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<script lang="ts">
import { selectedExchangeCryptoCurrency, transakCryptoCurrencies, TransakCryptoCurrency } from '@auxiliary/transak'
import { IOption, SelectInput } from '@bloomwalletio/ui'
import { PopupTemplate } from '@components'
import { handleError } from '@core/error/handlers'
import { localize } from '@core/i18n'
import { networks } from '@core/network'
import { closePopup } from '@desktop/auxiliary/popup'
import { SearchInput } from '@ui'
import { TransakCryptoCurrencyTile } from '@views/dashboard/buy-sell/components'
let searchValue: string = ''
const options = [
{ value: 'all', label: localize('popups.transaction.allNetworks') },
...($networks?.reduce((acc, network) => {
if (!acc.find((option) => option.value === network.id)) {
acc.push({
value: network.id,
label: network.name,
})
}
return acc
}, [] as IOption[]) ?? []),
]
let selectedOption = options[0]
let filteredCryptoCurrencies = $transakCryptoCurrencies
function setFilteredfilteredCryptoCurrencies(): void {
if (selectedOption.value === 'all') {
filteredCryptoCurrencies = $transakCryptoCurrencies?.filter((cryptoCurrency) => {
const _searchValue = searchValue.toLowerCase()
return (
cryptoCurrency.name.toLowerCase().includes(_searchValue) ||
cryptoCurrency.symbol.toLowerCase().includes(_searchValue)
)
})
} else {
filteredCryptoCurrencies = $transakCryptoCurrencies?.filter((cryptoCurrency) => {
// TODO: map key to transak network name or compare chain id if possible?
const isInNetwork = cryptoCurrency.network.id === selectedOption.value
const _searchValue = searchValue.toLowerCase()
const isSearched =
cryptoCurrency.name.toLowerCase().includes(_searchValue) ||
cryptoCurrency.symbol.toLowerCase().includes(_searchValue)
return isInNetwork && isSearched
})
}
}
$: $transakCryptoCurrencies, searchValue, selectedOption, setFilteredfilteredCryptoCurrencies()
function onCryptoCurrencyClick(cryptoCurrency: TransakCryptoCurrency): void {
try {
if (cryptoCurrency === $selectedExchangeCryptoCurrency) {
onContinueClick()
} else {
$selectedExchangeCryptoCurrency = cryptoCurrency
}
} catch (err) {
handleError(err)
}
}
function onCancelClick(): void {
closePopup()
}
function onContinueClick(): void {
closePopup()
}
</script>

<PopupTemplate
title={localize('popups.transaction.selectToken')}
backButton={{ text: localize('actions.cancel'), onClick: onCancelClick }}
continueButton={{
text: localize('actions.continue'),
onClick: onContinueClick,
disabled: !$selectedExchangeCryptoCurrency,
}}
>
<div class="flex-1 h-0 flex flex-col gap-4">
<div class="flex-none flex flex-col gap-4">
{#if $networks.length > 1}
<SelectInput bind:selected={selectedOption} {options} hideValue />
{/if}
<SearchInput bind:value={searchValue} />
</div>
<div class="-mr-3 overflow-y-scroll">
<token-list class="flex flex-col p-0.5 pr-1.5 gap-2">
{#each filteredCryptoCurrencies ?? [] as cryptoCurrency}
{@const selected =
$selectedExchangeCryptoCurrency?.name === cryptoCurrency.name &&
$selectedExchangeCryptoCurrency?.network.id === cryptoCurrency?.network.id}
<TransakCryptoCurrencyTile
{cryptoCurrency}
onClick={() => onCryptoCurrencyClick(cryptoCurrency)}
{selected}
/>
{/each}
</token-list>
</div>
</div>
</PopupTemplate>
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export enum PopupId {
SyncAccounts = 'syncAccounts',
TestDeepLinkForm = 'testDeepLinkForm',
TokenInformation = 'tokenInformation',
TransakSelectToken = 'transakSelectToken',
VoteForProposal = 'voteForProposal',
VotingPowerToZero = 'votingPowerToZero',
}
6 changes: 3 additions & 3 deletions packages/desktop/lib/electron/managers/transak.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export default class TransakManager implements ITransakManager {
}

private getUrl(data: ITransakWindowData): string {
const { address, currency, service, amount, paymentMethod } = data
const { address, currency, service, amount, paymentMethod, networkName, cryptoCurrencySymbol } = data
const apiKey = process.env.TRANSAK_API_KEY

if (typeof apiKey !== 'string') {
Expand Down Expand Up @@ -248,8 +248,8 @@ export default class TransakManager implements ITransakManager {
walletAddress: address,
paymentMethod: paymentMethod,
productsAvailed: service,
cryptoCurrencyCode: 'IOTA',
network: 'miota',
cryptoCurrencyCode: cryptoCurrencySymbol,
network: networkName,
themeColor: '7C41C9',
hideMenu: true,
disableWalletAddressForm: true,
Expand Down
3 changes: 2 additions & 1 deletion packages/desktop/views/dashboard/buy-sell/BuySell.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
import { BuySellMainView } from './views'
import { dashboardRoute, DashboardRoute } from '@core/router'
import { onMount } from 'svelte'
import { updateTransakFiatCurrencies } from '@auxiliary/transak'
import { updateTransakCryptoCurrencies, updateTransakFiatCurrencies } from '@auxiliary/transak'
$: if (features.analytics.dashboardRoute.buySell.enabled && $dashboardRoute === DashboardRoute.BuySell) {
Platform.trackEvent('buy-sell-route', { route: $dashboardRoute })
}
onMount(() => {
void updateTransakFiatCurrencies()
void updateTransakCryptoCurrencies()
})
</script>

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script lang="ts">
import { TransakCryptoCurrency } from '@auxiliary/transak'
import { Avatar } from '@bloomwalletio/ui'
import { CoinGeckoCoinImage } from '@core/market/interfaces'
import { NetworkBadge } from '@ui/badges'
export let cryptoCurrency: TransakCryptoCurrency
export let size: 'xxs' | 'xs' | 'sm' | 'base' | 'md' | 'lg' = 'md'
export let hideNetworkBadge: boolean = false
const IMAGE_SIZES: Record<typeof size, keyof CoinGeckoCoinImage> = {
xxs: 'thumb',
xs: 'thumb',
sm: 'thumb',
base: 'small',
md: 'small',
lg: 'small',
}
let imageLoadError = false
$: image = cryptoCurrency?.image[IMAGE_SIZES[size]]
</script>

<div class="avatar">
<Avatar {size} backgroundColor="brand/10">
{#if image && !imageLoadError}
<img
src={image}
alt={cryptoCurrency.name}
class="w-full h-full object-cover"
on:error={() => (imageLoadError = true)}
/>
{/if}
</Avatar>
{#if (size === 'base' || size === 'md' || size === 'lg') && !hideNetworkBadge}
<span class="relative flex justify-center items-center bottom-0 right-0">
<NetworkBadge size="xs" networkId={cryptoCurrency.network.id} />
</span>
{/if}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import { Tile, Text, Pill } from '@bloomwalletio/ui'
import { TransakCryptoCurrency } from '@auxiliary/transak/stores'
import TransakCryptoCurrencyAvatar from './TransakCryptoCurrencyAvatar.svelte'
export let cryptoCurrency: TransakCryptoCurrency
export let onClick: (() => unknown) | undefined = undefined
export let selected = false
</script>

<Tile {onClick} {selected} surface={1} width="full">
<div class="w-full flex items-center gap-2">
<TransakCryptoCurrencyAvatar {cryptoCurrency} hideNetworkBadge />
<div class="flex w-full justify-between items-center">
<div class="flex flex-col">
<Text>{cryptoCurrency.symbol}</Text>
<Text fontWeight="medium">{cryptoCurrency.name}</Text>
</div>
<Pill color="brand" compact>
<Text type="xs" textColor="brand" transform="uppercase">{cryptoCurrency.network.name}</Text>
</Pill>
</div>
</div>
</Tile>
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@
import { isDashboardSideBarExpanded } from '@core/ui'
import { drawerState } from '@desktop/auxiliary/drawer/stores'
import { DrawerState } from '@desktop/auxiliary/drawer/types'
import { IPopupState, IProfileAuthPopupState, popupState, profileAuthPopup } from '@desktop/auxiliary/popup'
import {
IPopupState,
IProfileAuthPopupState,
openPopup,
PopupId,
popupState,
profileAuthPopup,
} from '@desktop/auxiliary/popup'
import { isFeatureEnabled } from '@lib/features/utils'
import { Pane } from '@ui'
import { onDestroy, tick } from 'svelte'
import { TokenTile, TransakAmountInput } from './'
import { transakFiatCurrencies } from '@auxiliary/transak'
import { TransakCryptoCurrencyTile, TransakAmountInput } from './'
import { selectedExchangeCryptoCurrency, transakCryptoCurrencies, transakFiatCurrencies } from '@auxiliary/transak'
const CURRENCY_OPTIONS: IOption[] = Object.keys(FiatCurrency).map((currency) => ({
value: currency,
Expand Down Expand Up @@ -65,7 +72,7 @@
state: IPopupState,
profilePopupState: IProfileAuthPopupState,
settingsState: ISettingsState,
drawerState: DrawerState
drawerState: DrawerState | undefined
): Promise<void> {
if (state.active || profilePopupState.active || settingsState.open || drawerState?.id) {
await Platform.hideTransak()
Expand Down Expand Up @@ -132,6 +139,10 @@
service: selectedTab.key as 'BUY' | 'SELL',
amount: Number(fiatValue),
paymentMethod: selectedPaymentOption.value ?? '',
networkName:
$selectedExchangeCryptoCurrency?.networkName ?? $transakCryptoCurrencies?.[0]?.networkName ?? 'miota',
cryptoCurrencySymbol:
$selectedExchangeCryptoCurrency?.symbol ?? $transakCryptoCurrencies?.[0]?.symbol ?? 'IOTA',
})
isTransakOpen = true
await updateTransakBounds()
Expand All @@ -142,6 +153,10 @@
isTransakOpen = false
}
function onTokenTileClick(): void {
openPopup({ id: PopupId.TransakSelectToken })
}
onDestroy(() => {
void Platform.closeTransak()
isTransakOpen = false
Expand Down Expand Up @@ -181,7 +196,12 @@
/>
</div>
<TransakAmountInput currency={selectedCurrency} bind:value={fiatValue} />
<TokenTile {fiatValue} currency={FiatCurrency[selectedCurrency]} />
{#if $transakCryptoCurrencies && $transakCryptoCurrencies.length > 0}
<TransakCryptoCurrencyTile
cryptoCurrency={$selectedExchangeCryptoCurrency ?? $transakCryptoCurrencies[0]}
onClick={onTokenTileClick}
/>
{/if}
<div class="w-full">
<SelectInput
label="Payment method"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { default as TokenTile } from './TokenTile.svelte'
export { default as TransakCryptoCurrencyTile } from './TransakCryptoCurrencyTile.svelte'
export { default as TransakAmountInput } from './TransakAmountInput.svelte'
export { default as TransakConnectionPanel } from './TransakConnectionPanel.svelte'
export { default as TransakExchangePanel } from './TransakExchangePanel.svelte'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import { ProfileActionsMenu, SidebarTab } from '@components'
import { APP_STAGE, AppStage } from '@core/app'
import { localize } from '@core/i18n'
import { SupportedStardustNetworkId } from '@core/network'
import { activeProfile, isSoftwareProfile } from '@core/profile/stores'
import {
DashboardRoute,
Expand All @@ -16,12 +15,12 @@
} from '@core/router'
import { isDashboardSideBarExpanded } from '@core/ui'
import { IDashboardSidebarTab } from '@desktop/routers'
import { isFeatureEnabled, isFeatureNotGeoFenced } from '@lib/features/utils'
import { Logo } from '@ui'
import { campaignsRouter } from '../campaigns'
import LedgerStatusTile from './LedgerStatusTile.svelte'
import StrongholdStatusTile from './StrongholdStatusTile.svelte'
import { BackupToast, VersionToast } from './toasts'
import { isFeatureEnabled, isFeatureNotGeoFenced } from '@lib/features/utils'
let expanded = true
function toggleExpand(): void {
Expand Down Expand Up @@ -77,11 +76,6 @@
label: localize('tabs.buySell'),
route: DashboardRoute.BuySell,
onClick: openBuySell,
disabled: $activeProfile?.network?.id !== SupportedStardustNetworkId.Iota,
tooltip:
$activeProfile?.network?.id !== SupportedStardustNetworkId.Iota
? localize('tabs.tooltips.buySell')
: '',
},
]
: []),
Expand Down
Loading

0 comments on commit dbe60be

Please sign in to comment.