Skip to content

Commit

Permalink
feat: adds multichain support in BuySell view
Browse files Browse the repository at this point in the history
  • Loading branch information
jeeanribeiro committed Jul 11, 2024
1 parent df243f7 commit b099298
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -1,83 +1,60 @@
<script lang="ts">
import { selectedExchangeCryptoCurrency, transakCryptoCurrencies, TransakCryptoCurrency } from '@auxiliary/transak'
import { SelectInput } from '@bloomwalletio/ui'
import { PopupTemplate } from '@components'
import { handleError } from '@core/error/handlers'
import { localize } from '@core/i18n'
import { getActiveNetworkId, networks } from '@core/network'
import { IToken, ITokenWithBalance, TokenStandard } from '@core/token'
import { getTokenBalance } from '@core/token/actions'
import { selectedAccountTokens } from '@core/token/stores'
import { networks } from '@core/network'
import { closePopup } from '@desktop/auxiliary/popup'
import { SearchInput, TokenAmountTile } from '@ui'
import { SearchInput } from '@ui'
import { IOption } from '@bloomwalletio/ui'
import { TransakCryptoCurrencyTile } from '@views/dashboard/buy-sell/components'
let searchValue: string = ''
let selectedToken: IToken | undefined = $selectedAccountTokens?.[getActiveNetworkId()]?.baseCoin
$: $selectedAccountTokens, searchValue, selectedOption, setFilteredTokenList()
const options = [
{ key: 'all', value: localize('popups.transaction.allNetworks') },
...($networks?.map((network) => ({ key: network.id, value: network.name })) ?? []),
{ value: 'all', label: localize('popups.transaction.allNetworks') },
...($transakCryptoCurrencies?.reduce((acc, cryptoCurrency) => {
if (!acc.find((option) => option.value === cryptoCurrency.networkName)) {
acc.push({ value: cryptoCurrency.networkName, label: cryptoCurrency.networkName.toUpperCase() })
}
return acc
}, [] as IOption[]) ?? []),
]
let selectedOption = options[0]
let tokenList: ITokenWithBalance[]
function getSortedTokenForAllNetworks(): ITokenWithBalance[] {
const baseCoins: ITokenWithBalance[] = []
const nativeTokens: ITokenWithBalance[] = []
for (const networkTokens of Object.values($selectedAccountTokens)) {
if (networkTokens?.baseCoin) {
baseCoins.push(networkTokens.baseCoin)
}
nativeTokens.push(...(networkTokens?.nativeTokens ?? []))
}
return [
...baseCoins,
...nativeTokens.sort((a, b) => {
const nameA = a.metadata?.name.toLowerCase() ?? ''
const nameB = b.metadata?.name.toLowerCase() ?? ''
return nameA.localeCompare(nameB)
}),
]
}
function setFilteredTokenList(): void {
const sortedTokens = getSortedTokenForAllNetworks()
tokenList = sortedTokens.filter(isVisibleToken)
if (!tokenList.some((token) => token.id === selectedToken?.id)) {
selectedToken = undefined
}
}
function isVisibleToken(token: ITokenWithBalance): boolean {
const _searchValue = searchValue.toLowerCase()
const name = token?.metadata?.name
const ticker =
token?.metadata?.standard === TokenStandard.BaseToken ? token?.metadata.unit : token?.metadata?.symbol
const visibleNetwork = selectedOption.key === 'all' || selectedOption.key === token.networkId
if (_searchValue) {
return (
visibleNetwork &&
!!(
(name && name.toLowerCase().includes(_searchValue)) ||
(ticker && ticker.toLowerCase().includes(_searchValue))
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 {
return visibleNetwork
filteredCryptoCurrencies = $transakCryptoCurrencies?.filter((cryptoCurrency) => {
// TODO: map key to transak network name or compare chain id if possible?
const isInNetwork = cryptoCurrency.networkName === 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 onTokenClick(token: ITokenWithBalance): void {
function onCryptoCurrencyClick(cryptoCurrency: TransakCryptoCurrency): void {
try {
if (token === selectedToken) {
if (cryptoCurrency === $selectedExchangeCryptoCurrency) {
onContinueClick()
} else {
selectedToken = token
$selectedExchangeCryptoCurrency = cryptoCurrency
}
} catch (err) {
handleError(err)
Expand All @@ -99,25 +76,26 @@
continueButton={{
text: localize('actions.continue'),
onClick: onContinueClick,
disabled: !selectedToken,
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} />
<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 tokenList as token}
{@const selected = selectedToken?.id === token.id && selectedToken?.networkId === token?.networkId}
<TokenAmountTile
{token}
{#each filteredCryptoCurrencies ?? [] as cryptoCurrency}
{@const selected =
$selectedExchangeCryptoCurrency?.name === cryptoCurrency.name &&
$selectedExchangeCryptoCurrency?.networkName === cryptoCurrency?.networkName}
<TransakCryptoCurrencyTile
{cryptoCurrency}
onClick={() => onCryptoCurrencyClick(cryptoCurrency)}
{selected}
amount={getTokenBalance(token.id, token.networkId)?.available}
onClick={() => onTokenClick(token)}
/>
{/each}
</token-list>
Expand Down
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

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.networkName} />
</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.networkName}</Text>
</Pill>
</div>
</div>
</Tile>
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
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 @@ -72,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 @@ -139,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 Down Expand Up @@ -192,7 +196,12 @@
/>
</div>
<TransakAmountInput currency={selectedCurrency} bind:value={fiatValue} />
<TokenTile {fiatValue} currency={FiatCurrency[selectedCurrency]} onClick={onTokenTileClick} />
{#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
@@ -1,9 +1,13 @@
import { TransakApi } from '../apis'
import { TransakCryptoCurrencies, transakCryptoCurrencies } from '../stores'
import { TransakCryptoCurrency, transakCryptoCurrencies } from '../stores'

export async function updateTransakCryptoCurrencies(): Promise<void> {
// TODO: dynamically generate list of allowed names
const allowedNetworkNames = ['miota', 'ethereum']
const allowedNetworkChainIds = ['1']

const api = new TransakApi()
const { response } = (await api.getCryptoCurrencies()) ?? {}
const response = await api.getFilteredCryptoCurrencies(allowedNetworkNames, allowedNetworkChainIds)

transakCryptoCurrencies.set(
response?.reduce((acc, token) => {
Expand All @@ -14,6 +18,8 @@ export async function updateTransakCryptoCurrencies(): Promise<void> {
return [
...acc,
{
name: token.name,
symbol: token.symbol,
image: {
thumb: token.image.thumb,
small: token.image.small,
Expand All @@ -24,6 +30,6 @@ export async function updateTransakCryptoCurrencies(): Promise<void> {
decimals: token.decimals,
},
]
}, [] as TransakCryptoCurrencies)
}, [] as TransakCryptoCurrency[])
)
}
Loading

0 comments on commit b099298

Please sign in to comment.