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: multiple isc chains #2125

Closed
wants to merge 11 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@
import { Router } from '@core/router'
import { NetworkConfigRoute } from '../'
import { AddIscpChainForm } from './components'
import { Button } from '@bloomwalletio/ui'

export let drawerRouter: Router<NetworkConfigRoute>

let form: AddIscpChainForm
let disabled: boolean
</script>

<DrawerTemplate title={localize('views.dashboard.drawers.networkConfig.addChain.title')} {drawerRouter}>
<AddIscpChainForm />
<AddIscpChainForm bind:this={form} bind:disabled />
<div slot="footer">
<Button text={localize('actions.addChain')} on:click={form.onSubmitClick} width="full" {disabled} />
</div>
</DrawerTemplate>
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<script lang="ts">
import { Icon as IconEnum } from '@auxiliary/icon'
import { DrawerTemplate, NetworkCard } from '@components'
import { localize } from '@core/i18n'
import { clearSelectedChain, networks, networkStatus } from '@core/network'
import { Router } from '@core/router'
import networkFeatures from '@features/network.features'
import { Icon } from '@ui'
import { onMount } from 'svelte'
import { NetworkConfigRoute, networkConfigRouter } from '../'
import { Button, IconName } from '@bloomwalletio/ui'

export let drawerRouter: Router<NetworkConfigRoute>

Expand All @@ -29,15 +28,15 @@
{/each}
{/key}
</div>
</connected-chains-drawer>
<div slot="footer" class="flex justify-center">
{#if networkFeatures.config.addChain.enabled}
<button
type="button"
class="flex flex-row items-center justify-center w-full space-x-2 bg-transparent text-blue-500 px-8 py-3 text-15 rounded-lg"
on:click|stopPropagation={onAddChainClick}
>
<Icon icon={IconEnum.Plus} height={12} />
{localize('actions.addChain')}
</button>
<Button
variant="text"
icon={IconName.Plus}
text={localize('actions.addChain')}
on:click={onAddChainClick}
/>
{/if}
</connected-chains-drawer>
</div>
</DrawerTemplate>
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,27 @@
ETHEREUM_COIN_TYPE,
EvmNetworkId,
NetworkNamespace,
getNetwork,
ChainId,
getActiveNetworkId,
StardustNetwork,
} from '@core/network'
import { activeProfile } from '@core/profile/stores'
import { getNetworkHrp } from '@core/profile/actions'
import { isValidHexAddress, isValidHttpsUrl, validateBech32Address } from '@core/utils'
import { Button } from '@bloomwalletio/ui'
import { Input } from '@ui'
import { TextInput } from '@bloomwalletio/ui'

export let disabled: boolean = false

const localeKey = 'views.dashboard.drawers.networkConfig.chain'

const isBusy = false
let nameError = ''
let aliasAddressError = ''
let rpcEndpointError = ''
let explorerUrlError = ''
$: submitDisabled = !evmNetwork.name || !evmNetwork.aliasAddress || !evmNetwork.rpcEndpoint
const chainIdError = ''

$: disabled = !evmNetwork.name || !evmNetwork.id || !evmNetwork.aliasAddress || !evmNetwork.rpcEndpoint

const evmNetwork: IIscpEvmNetworkConfiguration = {
type: EvmNetworkType.Iscp,
Expand All @@ -34,6 +39,7 @@
aliasAddress: '',
rpcEndpoint: '',
apiEndpoint: '',
explorerUrl: '',
coinType: ETHEREUM_COIN_TYPE,
}

Expand Down Expand Up @@ -92,49 +98,38 @@
explorerUrlError = ''
}

function onSubmitClick(): void {
export function onSubmitClick(): void {
resetErrors()
validate()
const hasError = !!nameError || !!aliasAddressError || !!rpcEndpointError || !!explorerUrlError
if (!hasError) {
// TODO: https://github.com/iotaledger/firefly/issues/6375
const hasError =
!!nameError || !!aliasAddressError || !!rpcEndpointError || !!chainIdError || !!explorerUrlError
if (hasError) {
return
}
// TODO: decouple addChain() function from StardustNetwork
const stardustNetwork = getNetwork(getActiveNetworkId()) as StardustNetwork
stardustNetwork?.addChain(evmNetwork)
}
</script>

<add-iscp-network class="h-full flex flex-col justify-between">
<form id="add-network-form" class="flex flex-col gap-3" on:submit|preventDefault={onSubmitClick}>
<Input
bind:value={evmNetwork.name}
placeholder={localize('general.name')}
disabled={isBusy}
error={nameError}
/>
<Input
<form id="add-network-form" class="flex flex-col gap-4 px-6" on:submit|preventDefault={onSubmitClick}>
<TextInput bind:value={evmNetwork.name} label={localize('general.name')} error={nameError} />
<TextInput bind:value={evmNetwork.id} label={localize(`${localeKey}.chainId`)} error={chainIdError} />
<TextInput
bind:value={evmNetwork.aliasAddress}
placeholder={localize(`${localeKey}.aliasAddress`)}
disabled={isBusy}
label={localize(`${localeKey}.aliasAddress`)}
error={aliasAddressError}
/>
<Input
<TextInput
bind:value={evmNetwork.rpcEndpoint}
placeholder={localize(`${localeKey}.rpcEndpoint`)}
disabled={isBusy}
label={localize(`${localeKey}.rpcEndpoint`)}
error={rpcEndpointError}
/>
<Input
<TextInput
bind:value={evmNetwork.explorerUrl}
placeholder={localize(`${localeKey}.explorerEndpoint`)}
disabled={isBusy}
label={localize(`${localeKey}.explorerUrl`)}
error={explorerUrlError}
/>
</form>
<Button
type="submit"
form="add-network-form"
width="full"
disabled={submitDisabled || isBusy}
busy={isBusy}
text={localize('actions.addChain')}
/>
</add-iscp-network>
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@
import { networks } from '@core/network'

export let account: IAccountState

$: accountNetworks = $networks ?? []
</script>

<Pane
classes="
w-full flex shrink-0 grid {$networks?.length && $networks.length > 1 ? 'grid-cols-3' : 'grid-cols-2'}
w-full flex shrink-0 grid {accountNetworks.length > 0
? accountNetworks.length > 1
? 'grid-cols-4'
: 'grid-cols-3'
: 'grid-cols-2'}
bg-surface dark:bg-surface-dark
border border-solid border-stroke dark:border-stroke-dark
divide-x divide-solid divide-stroke dark:divide-stroke-dark
shadow-lg
"
>
<AccountSummary />
{#if $networks}
<AccountNetworkSummary {account} network={$networks[0]} />
{#if $networks[1]}
<AccountNetworkSummary {account} network={$networks[1]} />
{/if}
{/if}
{#each accountNetworks as network}
<AccountNetworkSummary {account} {network} />
{/each}
</Pane>
4 changes: 2 additions & 2 deletions packages/shared/src/components/inputs/NetworkInput.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { IOption, SelectInput } from '@bloomwalletio/ui'
import { localize } from '@core/i18n'
import { NetworkId, getEvmNetworks, getL1Network } from '@core/network'
import { NetworkId, getEvmNetworks, getStardustNetwork } from '@core/network'

export let networkId: NetworkId | undefined
export let error: string | undefined
Expand All @@ -28,7 +28,7 @@
function getNetworkOptions(showLayer2: boolean): IOption[] {
const options: IOption[] = []
if (showLayer1) {
const l1Network = getL1Network()
const l1Network = getStardustNetwork()
options.push({ label: l1Network.name, value: l1Network.id })
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { getIscpChains, getL1Network } from '@core/network'
import { getIscpChains, getStardustNetwork } from '@core/network'
import { NetworkFilterUnit } from '@core/utils/interfaces/filter'
import features from '@features/features'
import { IOption, SelectInput } from '@bloomwalletio/ui'
Expand All @@ -10,7 +10,7 @@
let selected: IOption | undefined = options.find((option) => option.value === filterUnit.selected) ?? options?.[0]

function getOptions(): IOption[] {
const l1Network = getL1Network()
const l1Network = getStardustNetwork()

const iscpChains = features?.network?.layer2?.enabled ? getIscpChains() : []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { OnboardingNetworkType } from '@contexts/onboarding'
import { localize } from '@core/i18n'
import { INode } from '@iota/sdk/out/types'
import { DEFAULT_NETWORK_METADATA, EMPTY_NODE } from '@core/network/constants'
import { DEFAULT_STARDUST_NETWORK_METADATA, EMPTY_NODE } from '@core/network/constants'
import { IClientOptions, INodeInfoResponse } from '@core/network/interfaces'
import { nodeInfo } from '@core/network/stores'
import {
Expand Down Expand Up @@ -47,7 +47,7 @@
})

function getNetworkTypeOptions(): IOption[] {
const options = Object.values(DEFAULT_NETWORK_METADATA).map((network) => ({
const options = Object.values(DEFAULT_STARDUST_NETWORK_METADATA).map((network) => ({
label: network?.name,
value: getOnboardingNetworkTypeFromNetworkId(network?.id),
}))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-nocheck - This file is not being type checked because the migrations and types are not defined in our code base

import {
DEFAULT_EVM_NETWORK_CONFIGURATIONS,
DEFAULT_ISC_NETWORK_CONFIGURATIONS_PER_STARDUST_NETWORK,
IIscpEvmNetworkMetadata,
getDefaultPersistedNetwork,
getNetworkIdFromOnboardingNetworkType,
Expand Down Expand Up @@ -240,7 +240,9 @@ export function fireflyStardustProfileMigrationToV13(existingProfile: unknown):

const newNetwork = oldNetwork as unknown as IThirdPartyPersistedNetwork
const maybeDefaultChainConfig =
DEFAULT_EVM_NETWORK_CONFIGURATIONS[getNetworkIdFromOnboardingNetworkType(existingProfile.network.id)]
DEFAULT_ISC_NETWORK_CONFIGURATIONS_PER_STARDUST_NETWORK[
getNetworkIdFromOnboardingNetworkType(existingProfile.network.id)
]

const defaultChainConfig: IIscpEvmNetworkMetadata[] = maybeDefaultChainConfig ? [maybeDefaultChainConfig] : []

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { IPersistedAccountData } from '@core/account'
import { MarketCurrency } from '@core/market'
import {
DEFAULT_EVM_NETWORK_CONFIGURATIONS,
IPersistedNetwork,
DEFAULT_ISC_NETWORK_CONFIGURATIONS_PER_STARDUST_NETWORK,
IPersistedStardustNetwork,
NetworkNamespace,
StardustNetworkId,
} from '@core/network'
Expand Down Expand Up @@ -69,11 +69,15 @@ export function buildPersistedProfileFromThirdPartyPersistedProfile(
return persistedProfile
}

function buildPersistedNetworkFromThirdPartyPersistedNetwork(network: IThirdPartyPersistedNetwork): IPersistedNetwork {
function buildPersistedNetworkFromThirdPartyPersistedNetwork(
network: IThirdPartyPersistedNetwork
): IPersistedStardustNetwork {
const networkId: StardustNetworkId =
NETWORK_NAME_TO_STARDUST_NETWORK_ID_MAP[network.protocol.networkName] ??
`${NetworkNamespace.Stardust}:${network.protocol.networkName}`
const defaultChainConfigurations = structuredClone(DEFAULT_EVM_NETWORK_CONFIGURATIONS?.[networkId])
const defaultChainConfigurations = structuredClone(
DEFAULT_ISC_NETWORK_CONFIGURATIONS_PER_STARDUST_NETWORK?.[networkId]
)

return {
id: networkId,
Expand All @@ -83,7 +87,7 @@ function buildPersistedNetworkFromThirdPartyPersistedNetwork(network: IThirdPart
coinType: network.coinType,
protocol: network.protocol,
baseToken: network.baseToken,
chainConfigurations: defaultChainConfigurations ? [defaultChainConfigurations] : [],
chainConfigurations: defaultChainConfigurations ? defaultChainConfigurations : [],
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function convertOnboardingProfileToPersistedProfile(
...structuredClone(DEFAULT_PERSISTED_PROFILE_OBJECT),
...(onboardingProfile?.id && { id: onboardingProfile.id }),
...(onboardingProfile?.name && { name: onboardingProfile.name }),
...(onboardingProfile?.network && { network: onboardingProfile.network }),
network: onboardingProfile.network,
...(onboardingProfile?.type && { type: onboardingProfile.type }),
...(onboardingProfile?.lastStrongholdBackupTime && {
lastStrongholdBackupTime: onboardingProfile.lastStrongholdBackupTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function checkForUntrackedTokens(account: IAccountState, addPreviouslyUnt
const evmNetworks = getEvmNetworks()
evmNetworks?.forEach(async (evmNetwork) => {
const evmAddress = account.evmAddresses[evmNetwork.coinType]
if (!evmAddress) {
if (!evmAddress || !evmNetwork.explorerUrl) {
return
}
const networkId = evmNetwork.id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EvmNetworkId } from '@core/network'
import { SupportedEvmNetworkId } from '@core/network/constants/supported-network-id.constant'
import { SupportedIscNetworkId } from '@core/network/constants/supported-network-id.constant'

export const BASE_TOKEN_CONTRACT_ADDRESS: Readonly<{ [id in EvmNetworkId]?: string }> = {
[SupportedEvmNetworkId.ShimmerEvm]: '0x1074010000000000000000000000000000000000',
[SupportedEvmNetworkId.TestnetEvm]: '0x1074010000000000000000000000000000000000',
[SupportedIscNetworkId.ShimmerEvm]: '0x1074010000000000000000000000000000000000',
[SupportedIscNetworkId.TestnetEvm]: '0x1074010000000000000000000000000000000000',
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { get } from 'svelte/store'
import { CoinGeckoApi } from '../apis'
import { coinGeckoTokensMetadata } from '../stores'
import { CoinGeckoNetworkId } from '../enums'
import { SupportedEvmNetworkId } from '@core/network'
import { SupportedIscNetworkId } from '@core/network'

export async function getAndUpdateShimmerEvmTokensMetadata(): Promise<void> {
try {
const coinGeckoShimmerEvmTokens = await CoinGeckoApi.getFilteredCoinsList(CoinGeckoNetworkId.ShimmerEVM)
const networkId = SupportedEvmNetworkId.ShimmerEvm
const networkId = SupportedIscNetworkId.ShimmerEvm
const tokenMetadataPromises = coinGeckoShimmerEvmTokens.map(async (token) => {
const tokenAddress = token.platforms[CoinGeckoNetworkId.ShimmerEVM]
if (get(coinGeckoTokensMetadata)?.[networkId]?.[tokenAddress]) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { derived, Readable } from 'svelte/store'
import { coinGeckoTokensMetadata } from './coingecko-tokens-metadata.store'
import { SupportedEvmNetworkId } from '@core/network/constants'
import { SupportedIscNetworkId } from '@core/network/constants'

export const shimmerEvmAddressToCoinGeckoIdMap: Readable<Record<string, string>> = derived(
coinGeckoTokensMetadata,
($coinGeckoTokensMetadata) => {
const shimmerEvmNetworkId = SupportedEvmNetworkId.ShimmerEvm
const shimmerEvmNetworkId = SupportedIscNetworkId.ShimmerEvm
const shimmerEvmTokens = $coinGeckoTokensMetadata?.[shimmerEvmNetworkId] ?? {}
const shimmerEvmTokensAddresses = Object.entries(shimmerEvmTokens ?? {}).reduce(
(acc, [tokenAddress, token]) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DEFAULT_EVM_NETWORK_CONFIGURATIONS } from '../constants'
import { DEFAULT_ISC_NETWORK_CONFIGURATIONS_PER_STARDUST_NETWORK } from '../constants'
import { getNetwork } from '../stores'
import { NetworkId } from '../types'

Expand All @@ -8,5 +8,7 @@ export function getNameFromNetworkId(networkId: NetworkId): string | undefined {
return networkName
}

return Object.values(DEFAULT_EVM_NETWORK_CONFIGURATIONS).find((config) => config?.id === networkId)?.name
return Object.values(DEFAULT_ISC_NETWORK_CONFIGURATIONS_PER_STARDUST_NETWORK).find(
(config) => config?.id === networkId
)?.name
}
Loading