From c898e89e8dcffa2bb8b8db5d501599a2e0f1852e Mon Sep 17 00:00:00 2001 From: Jean Ribeiro Date: Tue, 30 Apr 2024 09:29:39 -0300 Subject: [PATCH 1/4] feat: creates CollectionsGallery and CollectionsGalleryItem (#2395) * feat: creates CollectionsGallery and CollectionsGalleryItem * enhancement: NftGalleryItem * refactor: removes duplicated css * fix: stack border radius * fix: change NFT count Pill's color * fix: placeholder width --------- Co-authored-by: Mark Nardi --- .../components/CollectionsGallery.svelte | 63 ++++++++++ .../components/CollectionsGalleryItem.svelte | 78 +++++++++++++ .../collectibles/components/index.ts | 1 + .../views/CollectionsGalleryView.svelte | 7 +- .../molecules/NftGalleryItem.svelte | 109 ++++++++---------- packages/shared/src/locales/en.json | 1 + 6 files changed, 193 insertions(+), 66 deletions(-) create mode 100644 packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte create mode 100644 packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte diff --git a/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte b/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte new file mode 100644 index 0000000000..7722ef0aa8 --- /dev/null +++ b/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte @@ -0,0 +1,63 @@ + + + +
+ {#each item as collection} + {#if collection} + + {:else} +
+ {/if} + {/each} +
+ diff --git a/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte b/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte new file mode 100644 index 0000000000..816018a68a --- /dev/null +++ b/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte @@ -0,0 +1,78 @@ + + + + + diff --git a/packages/desktop/views/dashboard/collectibles/components/index.ts b/packages/desktop/views/dashboard/collectibles/components/index.ts index cb1cd98401..9dfe83c31e 100644 --- a/packages/desktop/views/dashboard/collectibles/components/index.ts +++ b/packages/desktop/views/dashboard/collectibles/components/index.ts @@ -1,3 +1,4 @@ export { default as CollectiblesTabs } from './CollectiblesTabs.svelte' +export { default as CollectionsGallery } from './CollectionsGallery.svelte' export { default as Erc721CollectibleDetails } from './Erc721CollectibleDetails.svelte' export { default as Irc27CollectibleDetails } from './Irc27CollectibleDetails.svelte' diff --git a/packages/desktop/views/dashboard/collectibles/views/CollectionsGalleryView.svelte b/packages/desktop/views/dashboard/collectibles/views/CollectionsGalleryView.svelte index 28f84f689d..068bde93a3 100644 --- a/packages/desktop/views/dashboard/collectibles/views/CollectionsGalleryView.svelte +++ b/packages/desktop/views/dashboard/collectibles/views/CollectionsGalleryView.svelte @@ -5,7 +5,7 @@ import { PopupId, openPopup } from '@desktop/auxiliary/popup' import features from '@features/features' import { SearchInput } from '@ui' - import { CollectiblesTabs } from '../components' + import { CollectiblesTabs, CollectionsGallery } from '../components' import { collectionsSearchTerm, selectedAccountCollections } from '@core/nfts/stores' import { Collections, isVisibleCollection } from '@core/nfts' @@ -48,10 +48,7 @@ {#if hasCollections} {#if Object.keys(queriedCollections).length > 0} - - {#each Object.keys(queriedCollections) as collection} - {queriedCollections[collection].name} - {/each} + {:else}
- diff --git a/packages/shared/src/locales/en.json b/packages/shared/src/locales/en.json index 087735e3be..24576b9ee4 100644 --- a/packages/shared/src/locales/en.json +++ b/packages/shared/src/locales/en.json @@ -1637,6 +1637,7 @@ "token": "Token", "unknownToken": "Unknown Token", "nft": "NFT", + "nfts": "{count, plural, one {# NFT} other {# NFTs}}", "type": "Type", "immutableIssuer": "Immutable Issuer", "magicContract": "Magic Contract", From 2fd36c0dec78bc6094872bb587eebd0926806f75 Mon Sep 17 00:00:00 2001 From: Jean Ribeiro Date: Tue, 30 Apr 2024 09:47:50 -0300 Subject: [PATCH 2/4] feat: adds CollectionDetails (#2396) * feat: creates CollectionsGallery and CollectionsGalleryItem * enhancement: NftGalleryItem * refactor: removes duplicated css * fix: stack border radius * fix: change NFT count Pill's color * feat: adds CollectionDetails * fix: code cleanup --- .../components/CollectionDetails.svelte | 14 ++++++++++ .../components/CollectionsGallery.svelte | 4 ++- .../components/CollectionsGalleryItem.svelte | 7 +++-- .../collectibles/components/index.ts | 1 + .../views/CollectiblesDetailsView.svelte | 28 ++++++++++++------- .../dashboard/components/Breadcrumbs.svelte | 3 +- .../molecules/NftGalleryItem.svelte | 3 +- .../nfts/interfaces/collection.interface.ts | 1 + .../shared/src/lib/core/nfts/stores/index.ts | 1 + .../nfts/stores/selected-collection.store.ts | 3 ++ .../router/routers/collectibles-router.ts | 2 ++ 11 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 packages/desktop/views/dashboard/collectibles/components/CollectionDetails.svelte create mode 100644 packages/shared/src/lib/core/nfts/stores/selected-collection.store.ts diff --git a/packages/desktop/views/dashboard/collectibles/components/CollectionDetails.svelte b/packages/desktop/views/dashboard/collectibles/components/CollectionDetails.svelte new file mode 100644 index 0000000000..9fd3dede80 --- /dev/null +++ b/packages/desktop/views/dashboard/collectibles/components/CollectionDetails.svelte @@ -0,0 +1,14 @@ + + + diff --git a/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte b/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte index 7722ef0aa8..cdd80a5671 100644 --- a/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte +++ b/packages/desktop/views/dashboard/collectibles/components/CollectionsGallery.svelte @@ -6,7 +6,9 @@ export let collections: Collections - $: collectionsArray = Object.values(collections) + $: collectionsArray = Object.entries(collections).map(([id, collection]) => { + return { id, ...collection } + }) const COLLECTIONS_PER_CHUNK_FOR_SCREEN_SIZE = { sm: 2, diff --git a/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte b/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte index 816018a68a..f3e5fa3cf0 100644 --- a/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte +++ b/packages/desktop/views/dashboard/collectibles/components/CollectionsGalleryItem.svelte @@ -2,13 +2,16 @@ import { Collection } from '@core/nfts' import { AssetPillsForNft, MediaPlaceholder, NetworkAvatar, NftMedia } from '@ui' import { Pill, Text } from '@bloomwalletio/ui' - import { downloadingNftId } from '@core/nfts/stores' + import { downloadingNftId, selectedCollectionId } from '@core/nfts/stores' import { localize } from '@core/i18n' + import { CollectiblesRoute, collectiblesRouter } from '@core/router' export let collection: Collection function onCollectionClick(): void { - return + $selectedCollectionId = collection.id + $collectiblesRouter?.goTo(CollectiblesRoute.Details) + $collectiblesRouter?.setBreadcrumb(collection.name) } diff --git a/packages/desktop/views/dashboard/collectibles/components/index.ts b/packages/desktop/views/dashboard/collectibles/components/index.ts index 9dfe83c31e..af0c61c694 100644 --- a/packages/desktop/views/dashboard/collectibles/components/index.ts +++ b/packages/desktop/views/dashboard/collectibles/components/index.ts @@ -1,4 +1,5 @@ export { default as CollectiblesTabs } from './CollectiblesTabs.svelte' +export { default as CollectionDetails } from './CollectionDetails.svelte' export { default as CollectionsGallery } from './CollectionsGallery.svelte' export { default as Erc721CollectibleDetails } from './Erc721CollectibleDetails.svelte' export { default as Irc27CollectibleDetails } from './Irc27CollectibleDetails.svelte' diff --git a/packages/desktop/views/dashboard/collectibles/views/CollectiblesDetailsView.svelte b/packages/desktop/views/dashboard/collectibles/views/CollectiblesDetailsView.svelte index 45aaa4643b..a229d8dd67 100644 --- a/packages/desktop/views/dashboard/collectibles/views/CollectiblesDetailsView.svelte +++ b/packages/desktop/views/dashboard/collectibles/views/CollectiblesDetailsView.svelte @@ -1,21 +1,25 @@ - - {#if nft?.standard === NftStandard.Irc27} - - {:else if nft?.standard === NftStandard.Erc721} - - {/if} - +{#if collection} + +{:else} + + {#if nft?.standard === NftStandard.Irc27} + + {:else if nft?.standard === NftStandard.Erc721} + + {/if} + +{/if} diff --git a/packages/desktop/views/dashboard/components/Breadcrumbs.svelte b/packages/desktop/views/dashboard/components/Breadcrumbs.svelte index dc23e2fec8..ca23898239 100644 --- a/packages/desktop/views/dashboard/components/Breadcrumbs.svelte +++ b/packages/desktop/views/dashboard/components/Breadcrumbs.svelte @@ -6,6 +6,7 @@ CollectiblesRoute, DashboardRoute, GovernanceRoute, + collectiblesBreadcrumb, collectiblesRoute, collectiblesRouter, dashboardRoute, @@ -80,7 +81,7 @@ /> {#if $dashboardRoute === DashboardRoute.Collectibles && $collectiblesRoute !== CollectiblesRoute.Gallery} - + {/if} {#if $dashboardRoute === DashboardRoute.Governance && $governanceRoute !== GovernanceRoute.Proposals} diff --git a/packages/shared/src/components/molecules/NftGalleryItem.svelte b/packages/shared/src/components/molecules/NftGalleryItem.svelte index 0663ea66bc..1c11331963 100644 --- a/packages/shared/src/components/molecules/NftGalleryItem.svelte +++ b/packages/shared/src/components/molecules/NftGalleryItem.svelte @@ -2,7 +2,7 @@ import { Pill, Text, Tooltip, type TextColor } from '@bloomwalletio/ui' import { localize } from '@core/i18n' import { DownloadErrorType, IDownloadMetadata, Nft } from '@core/nfts' - import { downloadingNftId, selectedNftId } from '@core/nfts/stores' + import { downloadingNftId, selectedNftId, selectedCollectionId } from '@core/nfts/stores' import { CollectiblesRoute, collectiblesRouter } from '@core/router' import { MediaPlaceholder, NetworkAvatar, NftMedia } from '@ui' import AssetPillsForNft from '@ui/nfts/AssetPillsForNft.svelte' @@ -19,6 +19,7 @@ : ('brand' as TextColor) function onNftClick(): void { + $selectedCollectionId = undefined $selectedNftId = nft.id $collectiblesRouter?.goTo(CollectiblesRoute.Details) $collectiblesRouter?.setBreadcrumb(nft?.name) diff --git a/packages/shared/src/lib/core/nfts/interfaces/collection.interface.ts b/packages/shared/src/lib/core/nfts/interfaces/collection.interface.ts index 0d392293d2..24aaa2ca8f 100644 --- a/packages/shared/src/lib/core/nfts/interfaces/collection.interface.ts +++ b/packages/shared/src/lib/core/nfts/interfaces/collection.interface.ts @@ -2,6 +2,7 @@ import { NftStandard } from '../enums' import { Nft } from './nft.interface' export interface Collection { + id?: string standard: NftStandard name: string type: string diff --git a/packages/shared/src/lib/core/nfts/stores/index.ts b/packages/shared/src/lib/core/nfts/stores/index.ts index 45c2c513d3..c0b7aa9faf 100644 --- a/packages/shared/src/lib/core/nfts/stores/index.ts +++ b/packages/shared/src/lib/core/nfts/stores/index.ts @@ -6,4 +6,5 @@ export * from './selected-account-collections.store' export * from './persisted-nfts.store' export * from './selected-account-nfts.store' export * from './selected-collectibles-tabs.store' +export * from './selected-collection.store' export * from './selected-nft.store' diff --git a/packages/shared/src/lib/core/nfts/stores/selected-collection.store.ts b/packages/shared/src/lib/core/nfts/stores/selected-collection.store.ts new file mode 100644 index 0000000000..17f55e23bb --- /dev/null +++ b/packages/shared/src/lib/core/nfts/stores/selected-collection.store.ts @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store' + +export const selectedCollectionId = writable(undefined) diff --git a/packages/shared/src/lib/core/router/routers/collectibles-router.ts b/packages/shared/src/lib/core/router/routers/collectibles-router.ts index 0e37bc7b4d..2150121063 100644 --- a/packages/shared/src/lib/core/router/routers/collectibles-router.ts +++ b/packages/shared/src/lib/core/router/routers/collectibles-router.ts @@ -5,6 +5,7 @@ import { CollectiblesRoute } from '../enums' export const collectiblesRouter = writable(undefined) export const collectiblesRoute = writable(undefined) +export const collectiblesBreadcrumb = writable(undefined) export class CollectiblesRouter extends Router { protected breadcrumb: string | undefined @@ -15,6 +16,7 @@ export class CollectiblesRouter extends Router { setBreadcrumb(breadcrumb: string | undefined): void { this.breadcrumb = breadcrumb + collectiblesBreadcrumb.set(breadcrumb) } getBreadcrumb(): string | undefined { From c6f6b5bb2078aceeb764794152fa511ab1ea466c Mon Sep 17 00:00:00 2001 From: Mark Nardi Date: Tue, 30 Apr 2024 15:37:19 +0200 Subject: [PATCH 3/4] feat: fetch token balances for evm chains (#2380) * rename L2 to EVM * implement getBalance * check if profileId updated * revert poll interval --------- Co-authored-by: Tuditi <45079109+Tuditi@users.noreply.github.com> --- .../desktop/components/NetworkCard.svelte | 4 +- .../components/menus/TokenListMenu.svelte | 4 +- .../popup/popups/ReceiveAddressPopup.svelte | 6 +- .../components/AccountNetworkSummary.svelte | 4 +- .../account/actions/setSelectedAccount.ts | 4 +- .../actions/tryCreateAdditionalAccount.ts | 4 +- .../actions/fetchEvmBalancesForAccount.ts | 21 ++++++ .../actions/fetchL2BalanceForAccount.ts | 70 ------------------- .../src/lib/core/layer-2/actions/index.ts | 4 +- ...ccount.ts => pollEvmBalancesForAccount.ts} | 8 +-- ...s.ts => fetchEvmBalancesForAllAccounts.ts} | 6 +- .../src/lib/core/layer-2/utils/index.ts | 2 +- .../network/classes/base-evm-network.class.ts | 54 +++++++++++++- .../core/network/classes/isc-chain.class.ts | 19 +++-- .../interfaces/evm-network.interface.ts | 3 + .../profile/actions/active-profile/login.ts | 4 +- 16 files changed, 117 insertions(+), 100 deletions(-) create mode 100644 packages/shared/src/lib/core/layer-2/actions/fetchEvmBalancesForAccount.ts delete mode 100644 packages/shared/src/lib/core/layer-2/actions/fetchL2BalanceForAccount.ts rename packages/shared/src/lib/core/layer-2/actions/{pollL2BalanceForAccount.ts => pollEvmBalancesForAccount.ts} (68%) rename packages/shared/src/lib/core/layer-2/utils/{fetchL2BalanceForAllAccounts.ts => fetchEvmBalancesForAllAccounts.ts} (61%) diff --git a/packages/desktop/components/NetworkCard.svelte b/packages/desktop/components/NetworkCard.svelte index 130426b38e..3702067c7a 100644 --- a/packages/desktop/components/NetworkCard.svelte +++ b/packages/desktop/components/NetworkCard.svelte @@ -5,7 +5,7 @@ import { openUrlInBrowser } from '@core/app' import { handleError } from '@core/error/handlers' import { localize } from '@core/i18n' - import { generateAndStoreEvmAddressForAccounts, pollL2BalanceForAccount } from '@core/layer-2/actions' + import { generateAndStoreEvmAddressForAccounts, pollEvmBalancesForAccount } from '@core/layer-2/actions' import { LedgerAppName } from '@core/ledger' import { ExplorerEndpoint, Network, NetworkNamespace, getDefaultExplorerUrl, setSelectedChain } from '@core/network' import { ProfileType } from '@core/profile' @@ -67,7 +67,7 @@ network.coinType, $selectedAccount as IAccountState ) - pollL2BalanceForAccount($activeProfile.id, $selectedAccount as IAccountState) + pollEvmBalancesForAccount($activeProfile.id, $selectedAccount as IAccountState) if ($activeProfile.type === ProfileType.Ledger) { $networkConfigRouter.goTo(NetworkConfigRoute.ConfirmLedgerEvmAddress) } diff --git a/packages/desktop/components/menus/TokenListMenu.svelte b/packages/desktop/components/menus/TokenListMenu.svelte index 8b0611976a..8193c5b511 100644 --- a/packages/desktop/components/menus/TokenListMenu.svelte +++ b/packages/desktop/components/menus/TokenListMenu.svelte @@ -5,12 +5,12 @@ import { localize } from '@core/i18n' import { loadTokensForAllAccountBalances } from '@core/token/actions' import { PopupId, closePopup, openPopup } from '../../lib/auxiliary/popup' - import { fetchL2BalanceForAllAccounts } from '@core/layer-2' + import { fetchEvmBalancesForAllAccounts } from '@core/layer-2' let menu: Menu | undefined = undefined function onSyncTokensClick(): void { - fetchL2BalanceForAllAccounts($activeProfileId as string, true) + fetchEvmBalancesForAllAccounts($activeProfileId as string, true) showNotification({ variant: 'success', text: localize('notifications.syncTokens.success'), diff --git a/packages/desktop/components/popup/popups/ReceiveAddressPopup.svelte b/packages/desktop/components/popup/popups/ReceiveAddressPopup.svelte index cf476411c7..6284d743d1 100644 --- a/packages/desktop/components/popup/popups/ReceiveAddressPopup.svelte +++ b/packages/desktop/components/popup/popups/ReceiveAddressPopup.svelte @@ -5,8 +5,8 @@ import { selectedAccount } from '@core/account/stores' import { setClipboard } from '@core/utils' import { getActiveNetworkId, getNetwork, NetworkId, NetworkNamespace } from '@core/network' - import { generateAndStoreEvmAddressForAccounts, pollL2BalanceForAccount } from '@core/layer-2/actions' - import { activeProfile, activeProfileId } from '@core/profile/stores' + import { generateAndStoreEvmAddressForAccounts, pollEvmBalancesForAccount } from '@core/layer-2/actions' + import { activeProfile } from '@core/profile/stores' import { checkActiveProfileAuth } from '@core/profile/actions' import { LedgerAppName } from '@core/ledger' import PopupTemplate from '../PopupTemplate.svelte' @@ -42,7 +42,7 @@ try { await generateAndStoreEvmAddressForAccounts($activeProfile.type, coinType, account) - pollL2BalanceForAccount($activeProfileId as string, account) + pollEvmBalancesForAccount($activeProfile.id, account) updateNetworkNameAndAddress() } catch (error) { handleError(error) diff --git a/packages/desktop/views/dashboard/wallet/panes/account-summary/components/AccountNetworkSummary.svelte b/packages/desktop/views/dashboard/wallet/panes/account-summary/components/AccountNetworkSummary.svelte index 98cbf4db9b..9e10f5734b 100644 --- a/packages/desktop/views/dashboard/wallet/panes/account-summary/components/AccountNetworkSummary.svelte +++ b/packages/desktop/views/dashboard/wallet/panes/account-summary/components/AccountNetworkSummary.svelte @@ -2,7 +2,7 @@ import { AvatarGroup, Copyable, Text } from '@bloomwalletio/ui' import { FormattedBalance } from '@components' import { formatCurrency, localize } from '@core/i18n' - import { generateAndStoreEvmAddressForAccounts, pollL2BalanceForAccount } from '@core/layer-2/actions' + import { generateAndStoreEvmAddressForAccounts, pollEvmBalancesForAccount } from '@core/layer-2/actions' import { LedgerAppName } from '@core/ledger' import { Network, NetworkNamespace, setSelectedChain } from '@core/network' import { MimeType, Nft } from '@core/nfts' @@ -89,7 +89,7 @@ try { await generateAndStoreEvmAddressForAccounts($activeProfile.type, network.coinType, account) - pollL2BalanceForAccount($activeProfile.id, account) + pollEvmBalancesForAccount($activeProfile.id, account) if ($activeProfile.type === ProfileType.Ledger) { setSelectedChain(network) toggleDashboardDrawer({ diff --git a/packages/shared/src/lib/core/account/actions/setSelectedAccount.ts b/packages/shared/src/lib/core/account/actions/setSelectedAccount.ts index ef1b7a0ec7..682366997a 100644 --- a/packages/shared/src/lib/core/account/actions/setSelectedAccount.ts +++ b/packages/shared/src/lib/core/account/actions/setSelectedAccount.ts @@ -1,5 +1,5 @@ import { updateAccountForConnectedDapps } from '@auxiliary/wallet-connect/actions' -import { pollL2BalanceForAccount } from '@core/layer-2/actions/pollL2BalanceForAccount' +import { pollEvmBalancesForAccount } from '@core/layer-2/actions/pollEvmBalancesForAccount' import { activeAccounts, getActiveProfileId, updateActiveProfile } from '@core/profile/stores' import { clearFilters } from '@core/utils' import { resetSendOptionIndex } from '@core/wallet/stores' @@ -14,7 +14,7 @@ export function setSelectedAccount(index: number): void { updateAccountForConnectedDapps(account) updateActiveProfile({ lastUsedAccountIndex: index }) clearFilters() - pollL2BalanceForAccount(activeProfileId, account) + pollEvmBalancesForAccount(activeProfileId, account) resetSendOptionIndex() } else { throw new Error(`Account with ID ${index} cannot be found!`) diff --git a/packages/shared/src/lib/core/account/actions/tryCreateAdditionalAccount.ts b/packages/shared/src/lib/core/account/actions/tryCreateAdditionalAccount.ts index 8e21558ffe..03126be33f 100644 --- a/packages/shared/src/lib/core/account/actions/tryCreateAdditionalAccount.ts +++ b/packages/shared/src/lib/core/account/actions/tryCreateAdditionalAccount.ts @@ -6,7 +6,7 @@ import { createNewAccount } from './createNewAccount' import { setSelectedAccount } from './setSelectedAccount' import { getActiveProfile } from '@core/profile/stores' import { ProfileType } from '@core/profile' -import { generateAndStoreEvmAddressForAccounts, pollL2BalanceForAccount } from '@core/layer-2/actions' +import { generateAndStoreEvmAddressForAccounts, pollEvmBalancesForAccount } from '@core/layer-2/actions' import { getEvmNetworks } from '@core/network/stores' import { IError } from '@core/error/interfaces' @@ -24,7 +24,7 @@ export async function tryCreateAdditionalAccount(alias: string, color: string): const coinType = getEvmNetworks()[0]?.coinType if (coinType !== undefined) { void generateAndStoreEvmAddressForAccounts(activeProfile.type, coinType, account) - void pollL2BalanceForAccount(activeProfile.id, account) + void pollEvmBalancesForAccount(activeProfile.id, account) } } diff --git a/packages/shared/src/lib/core/layer-2/actions/fetchEvmBalancesForAccount.ts b/packages/shared/src/lib/core/layer-2/actions/fetchEvmBalancesForAccount.ts new file mode 100644 index 0000000000..9c5495af6b --- /dev/null +++ b/packages/shared/src/lib/core/layer-2/actions/fetchEvmBalancesForAccount.ts @@ -0,0 +1,21 @@ +import { IAccountState } from '@core/account/interfaces' +import { getEvmNetworks } from '@core/network/stores' +import { ITokenBalance } from '@core/token' +import { setLayer2AccountBalanceForChain } from '@core/layer-2/stores' +import { activeProfileId } from '@core/profile/stores' +import { get } from 'svelte/store' + +export function fetchEvmBalancesForAccount(profileId: string, account: IAccountState): void { + const evmNetworks = getEvmNetworks() + evmNetworks.forEach(async (evmNetwork) => { + try { + const tokenBalance: ITokenBalance = (await evmNetwork.getBalance(account)) ?? {} + + if (get(activeProfileId) === profileId) { + setLayer2AccountBalanceForChain(account.index, evmNetwork.id, tokenBalance) + } + } catch (error) { + console.error(error) + } + }) +} diff --git a/packages/shared/src/lib/core/layer-2/actions/fetchL2BalanceForAccount.ts b/packages/shared/src/lib/core/layer-2/actions/fetchL2BalanceForAccount.ts deleted file mode 100644 index 7d6c2a98ec..0000000000 --- a/packages/shared/src/lib/core/layer-2/actions/fetchL2BalanceForAccount.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { IAccountState } from '@core/account/interfaces' -import { ContractType, fetchIscAssetsForAccount } from '@core/layer-2' -import { IEvmNetwork } from '@core/network/interfaces' -import { getEvmNetworks } from '@core/network/stores' -import { updateErc721NftsOwnership } from '@core/nfts/actions' -import { getActiveProfile } from '@core/profile/stores' -import { getOrRequestTokenFromPersistedTokens } from '@core/token/actions' -import { Converter } from '@core/utils/convert' -import { ITokenBalance, TokenTrackingStatus } from '@core/token' -import features from '@features/features' -import { IError } from '@core/error' -import { isIscChain } from '@core/network/utils/isIscChain' -import { setLayer2AccountBalanceForChain } from '@core/layer-2/stores' - -export function fetchL2BalanceForAccount(profileId: string, account: IAccountState): void { - const { evmAddresses, index } = account - const evmNetworks = getEvmNetworks() - evmNetworks.forEach(async (evmNetwork) => { - const { coinType, id: networkId } = evmNetwork - const evmAddress = evmAddresses?.[coinType] - if (!evmAddress) { - return - } - - if (features.collectibles.erc721.enabled) { - void updateErc721NftsOwnership(account, evmNetwork.id) - } - - try { - const l2TokenBalance = isIscChain(evmNetwork) - ? await fetchIscAssetsForAccount(profileId, evmAddress, evmNetwork, account) - : {} - - const erc20Balances = await getErc20BalancesForAddress(evmAddress, evmNetwork) - for (const [tokenId, balance] of Object.entries(erc20Balances)) { - await getOrRequestTokenFromPersistedTokens(tokenId, networkId) - l2TokenBalance[tokenId] = Number.isNaN(Number(balance)) ? BigInt(0) : balance - } - setLayer2AccountBalanceForChain(index, networkId, l2TokenBalance) - } catch (error) { - console.error(error) - } - }) -} - -async function getErc20BalancesForAddress(evmAddress: string, evmNetwork: IEvmNetwork): Promise { - const networkId = evmNetwork.id - const coinType = evmNetwork.coinType - - const trackedTokens = getActiveProfile()?.trackedTokens?.[networkId] ?? {} - const erc20TokenBalances: ITokenBalance = {} - for (const [erc20Address, trackingStatus] of Object.entries(trackedTokens)) { - try { - if (trackingStatus === TokenTrackingStatus.Untracked) { - continue - } - - const contract = evmNetwork?.getContract(ContractType.Erc20, erc20Address) - if (!contract || !coinType) { - continue - } - const rawBalance = await contract.methods.balanceOf(evmAddress).call() - erc20TokenBalances[erc20Address] = Converter.bigIntLikeToBigInt(rawBalance) - } catch (err) { - const error = (err as IError)?.message ?? err - console.error(error) - } - } - return erc20TokenBalances -} diff --git a/packages/shared/src/lib/core/layer-2/actions/index.ts b/packages/shared/src/lib/core/layer-2/actions/index.ts index 3e38a7a390..3c52e199a7 100644 --- a/packages/shared/src/lib/core/layer-2/actions/index.ts +++ b/packages/shared/src/lib/core/layer-2/actions/index.ts @@ -2,12 +2,12 @@ export * from './buildUnwrapAssetParameters' export * from './buildUnwrapAssetTargetAddress' export * from './canAccountMakeEvmTransaction' export * from './checkForUntrackedTokens' -export * from './fetchL2BalanceForAccount' +export * from './fetchEvmBalancesForAccount' export * from './getGasFeeForLayer1ToLayer2Transaction' export * from './generateAndStoreEvmAddressForAccounts' export * from './getIscTransferSmartContractData' export * from './getLayer2MetadataForTransfer' export * from './getLayer2NetworkFromAddress' export * from './getNetworkFromAddress' -export * from './pollL2BalanceForAccount' +export * from './pollEvmBalancesForAccount' export * from './setGasFee' diff --git a/packages/shared/src/lib/core/layer-2/actions/pollL2BalanceForAccount.ts b/packages/shared/src/lib/core/layer-2/actions/pollEvmBalancesForAccount.ts similarity index 68% rename from packages/shared/src/lib/core/layer-2/actions/pollL2BalanceForAccount.ts rename to packages/shared/src/lib/core/layer-2/actions/pollEvmBalancesForAccount.ts index a1b24e38be..4e6b783924 100644 --- a/packages/shared/src/lib/core/layer-2/actions/pollL2BalanceForAccount.ts +++ b/packages/shared/src/lib/core/layer-2/actions/pollEvmBalancesForAccount.ts @@ -1,19 +1,19 @@ import { IAccountState } from '@core/account/interfaces' import { checkForUntrackedNfts } from '@core/nfts/actions' import { LAYER2_TOKENS_POLL_INTERVAL } from '../constants' -import { checkForUntrackedTokens, fetchL2BalanceForAccount } from '.' +import { checkForUntrackedTokens, fetchEvmBalancesForAccount } from '.' import { handleError } from '@core/error/handlers' let pollInterval: number -export function pollL2BalanceForAccount(profileId: string, account: IAccountState): void { +export function pollEvmBalancesForAccount(profileId: string, account: IAccountState): void { try { clearL2TokensPoll() checkForUntrackedTokens(account) void checkForUntrackedNfts(account) - fetchL2BalanceForAccount(profileId, account) + fetchEvmBalancesForAccount(profileId, account) pollInterval = window.setInterval(() => { - fetchL2BalanceForAccount(profileId, account) + fetchEvmBalancesForAccount(profileId, account) }, LAYER2_TOKENS_POLL_INTERVAL) } catch (err) { handleError(err) diff --git a/packages/shared/src/lib/core/layer-2/utils/fetchL2BalanceForAllAccounts.ts b/packages/shared/src/lib/core/layer-2/utils/fetchEvmBalancesForAllAccounts.ts similarity index 61% rename from packages/shared/src/lib/core/layer-2/utils/fetchL2BalanceForAllAccounts.ts rename to packages/shared/src/lib/core/layer-2/utils/fetchEvmBalancesForAllAccounts.ts index 044b7ddf7b..910d4a31d1 100644 --- a/packages/shared/src/lib/core/layer-2/utils/fetchL2BalanceForAllAccounts.ts +++ b/packages/shared/src/lib/core/layer-2/utils/fetchEvmBalancesForAllAccounts.ts @@ -1,14 +1,14 @@ import { get } from 'svelte/store' import { activeAccounts } from '@core/profile/stores' -import { checkForUntrackedTokens, fetchL2BalanceForAccount } from '../actions' +import { checkForUntrackedTokens, fetchEvmBalancesForAccount } from '../actions' import { checkForUntrackedNfts } from '@core/nfts/actions' -export function fetchL2BalanceForAllAccounts(profileId: string, addPreviouslyUntracked?: boolean): void { +export function fetchEvmBalancesForAllAccounts(profileId: string, addPreviouslyUntracked?: boolean): void { for (const account of get(activeAccounts)) { try { checkForUntrackedTokens(account, addPreviouslyUntracked) void checkForUntrackedNfts(account) - fetchL2BalanceForAccount(profileId, account) + fetchEvmBalancesForAccount(profileId, account) } catch (err) { console.error(err) } diff --git a/packages/shared/src/lib/core/layer-2/utils/index.ts b/packages/shared/src/lib/core/layer-2/utils/index.ts index c5a51f1934..6452d3c848 100644 --- a/packages/shared/src/lib/core/layer-2/utils/index.ts +++ b/packages/shared/src/lib/core/layer-2/utils/index.ts @@ -5,7 +5,7 @@ export * from './buildEvmTransactionDataForToken' export * from './calculateEstimatedGasFeeFromTransactionData' export * from './calculateMaxGasFeeFromTransactionData' export * from './fetchIscAssetsForAccount' -export * from './fetchL2BalanceForAllAccounts' +export * from './fetchEvmBalancesForAllAccounts' export * from './getAmountFromEvmTransactionValue' export * from './getEvmTokenMetadata' export * from './getErc20TransferSmartContractData' diff --git a/packages/shared/src/lib/core/network/classes/base-evm-network.class.ts b/packages/shared/src/lib/core/network/classes/base-evm-network.class.ts index ce3ba22361..6915c9068b 100644 --- a/packages/shared/src/lib/core/network/classes/base-evm-network.class.ts +++ b/packages/shared/src/lib/core/network/classes/base-evm-network.class.ts @@ -10,8 +10,15 @@ import { EvmNetworkType, NetworkHealth, NetworkNamespace, ChainId } from '../enu import { IBlock, IEvmNetwork, IBaseEvmNetworkConfiguration } from '../interfaces' import { CoinType } from '@iota/sdk/out/types' import { EvmNetworkId, Web3Provider } from '../types' -import { IBaseToken } from '@core/token' import { NETWORK_STATUS_POLL_INTERVAL } from '@core/network/constants' +import { BASE_TOKEN_ID, IBaseToken, ITokenBalance, TokenTrackingStatus } from '@core/token' +import features from '@features/features' +import { updateErc721NftsOwnership } from '@core/nfts/actions' +import { getOrRequestTokenFromPersistedTokens } from '@core/token/actions' +import { IAccountState } from '@core/account' +import { Converter } from '@core/utils' +import { getActiveProfile } from '@core/profile/stores' +import { IError } from '@core/error/interfaces' export class BaseEvmNetwork implements IEvmNetwork { public readonly provider: Web3Provider @@ -94,4 +101,49 @@ export class BaseEvmNetwork implements IEvmNetwork { const number = await this.provider.eth.getBlockNumber() return this.provider.eth.getBlock(number) } + + async getBalance(account: IAccountState): Promise { + const evmAddress = account.evmAddresses?.[this.coinType] + if (!evmAddress) { + return + } + + if (features.collectibles.erc721.enabled) { + void updateErc721NftsOwnership(account, this.id) + } + + const rawBalance = await this.provider.eth.getBalance(evmAddress) + const tokenBalance = { [BASE_TOKEN_ID]: Converter.bigIntLikeToBigInt(rawBalance) } + + const erc20Balances = await this.getErc20BalancesForAddress(evmAddress) + for (const [tokenId, balance] of Object.entries(erc20Balances)) { + await getOrRequestTokenFromPersistedTokens(tokenId, this.id) + tokenBalance[tokenId] = Number.isNaN(Number(balance)) ? BigInt(0) : balance + } + + return tokenBalance + } + + async getErc20BalancesForAddress(evmAddress: string): Promise { + const trackedTokens = getActiveProfile()?.trackedTokens?.[this.id] ?? {} + const erc20TokenBalances: ITokenBalance = {} + for (const [erc20Address, trackingStatus] of Object.entries(trackedTokens)) { + try { + if (trackingStatus === TokenTrackingStatus.Untracked) { + continue + } + + const contract = this.getContract(ContractType.Erc20, erc20Address) + if (!contract || !this.coinType) { + continue + } + const rawBalance = await contract.methods.balanceOf(evmAddress).call() + erc20TokenBalances[erc20Address] = Converter.bigIntLikeToBigInt(rawBalance) + } catch (err) { + const error = (err as IError)?.message ?? err + console.error(error) + } + } + return erc20TokenBalances + } } diff --git a/packages/shared/src/lib/core/network/classes/isc-chain.class.ts b/packages/shared/src/lib/core/network/classes/isc-chain.class.ts index ddfe4f0508..0fa6b2fb4b 100644 --- a/packages/shared/src/lib/core/network/classes/isc-chain.class.ts +++ b/packages/shared/src/lib/core/network/classes/isc-chain.class.ts @@ -1,6 +1,10 @@ -import { IBlock, IIscChainConfiguration, IIscChainMetadata } from '../interfaces' +import { IIscChainConfiguration, IIscChainMetadata } from '../interfaces' import { Converter } from '@core/utils' import { BaseEvmNetwork } from './base-evm-network.class' +import { IAccountState } from '@core/account/interfaces' +import { ITokenBalance } from '@core/token/interfaces' +import { fetchIscAssetsForAccount } from '@core/layer-2/utils' +import { getActiveProfileId } from '@core/profile/stores' export class IscChain extends BaseEvmNetwork { private readonly _chainApi: string @@ -47,9 +51,16 @@ export class IscChain extends BaseEvmNetwork { return (await response.json()) as IIscChainMetadata } - async getLatestBlock(): Promise { - const number = await this.provider.eth.getBlockNumber() - return this.provider.eth.getBlock(number) + async getBalance(account: IAccountState): Promise { + const evmAddress = account.evmAddresses?.[this.coinType] + if (!evmAddress) { + return undefined + } + + const tokenBalance = (await super.getBalance(account)) ?? {} + const iscBalance = (await fetchIscAssetsForAccount(getActiveProfileId(), evmAddress, this, account)) ?? {} + + return { ...tokenBalance, ...iscBalance } } async getGasEstimate(hex: string): Promise { diff --git a/packages/shared/src/lib/core/network/interfaces/evm-network.interface.ts b/packages/shared/src/lib/core/network/interfaces/evm-network.interface.ts index 28c71ccf55..56bb333f0f 100644 --- a/packages/shared/src/lib/core/network/interfaces/evm-network.interface.ts +++ b/packages/shared/src/lib/core/network/interfaces/evm-network.interface.ts @@ -6,6 +6,8 @@ import { EvmNetworkId, Web3Provider } from '../types' import { IBlock } from './block.interface' import { IBaseNetwork, IBaseNetworkMetadata } from './base-network.interface' import { IIscChainMetadata } from './isc-chain-metadata.interface' +import { ITokenBalance } from '@core/token/interfaces' +import { IAccountState } from '@core/account/interfaces' export interface IIscChain extends IEvmNetwork { apiEndpoint: string @@ -26,6 +28,7 @@ export interface IEvmNetwork extends IBaseNetwork, IBaseNetworkMetadata { provider: Web3Provider getGasPrice(): Promise + getBalance(account: IAccountState): Promise getContract(type: ContractType, address: string): Contract getLatestBlock(): Promise diff --git a/packages/shared/src/lib/core/profile/actions/active-profile/login.ts b/packages/shared/src/lib/core/profile/actions/active-profile/login.ts index 44870af492..2aae66ebb8 100644 --- a/packages/shared/src/lib/core/profile/actions/active-profile/login.ts +++ b/packages/shared/src/lib/core/profile/actions/active-profile/login.ts @@ -4,7 +4,7 @@ import { generateAndStoreActivitiesForAllAccounts } from '@core/activity/actions import { Platform } from '@core/app/classes' import { AppContext } from '@core/app/enums' import { handleError } from '@core/error/handlers' -import { fetchL2BalanceForAllAccounts } from '@core/layer-2/utils' +import { fetchEvmBalancesForAllAccounts } from '@core/layer-2/utils' import { pollLedgerDeviceState } from '@core/ledger/actions' import { pollMarketPrices } from '@core/market/actions' import { loadNftsForActiveProfile } from '@core/nfts/actions' @@ -103,7 +103,7 @@ export async function login(loginOptions?: ILoginOptions): Promise { incrementLoginProgress() subscribeToWalletApiEventsForActiveProfile() await startBackgroundSync({ syncIncomingTransactions: true }) - fetchL2BalanceForAllAccounts(id) + fetchEvmBalancesForAllAccounts(_activeProfile.id) void fetchAndPersistTransactionsForAccounts(_activeProfile.id, get(activeAccounts)) // Step 8: finish login From 4f5d52015f678a20f2a7ccd2ee45d49f040bc0df Mon Sep 17 00:00:00 2001 From: Tuditi <45079109+Tuditi@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:09:34 +0200 Subject: [PATCH 4/4] chore: refactor evm network type (#2402) * rename L2 to EVM * implement getBalance * chore: rename EvmNetworkType * check if profileId updated * revert poll interval * refactor: simplify network classes inheritance Co-authored-by: Tuditi --------- Co-authored-by: Mark Nardi Co-authored-by: Nicole O'Brien Co-authored-by: Tuditi --- .../views/NetworkInformationDrawer.svelte | 6 +- .../views/components/AddIscChainForm.svelte | 4 +- .../send-flow/views/SelectTokenView.svelte | 1 + .../components/pills/NetworkTypePill.svelte | 8 +- .../layer-2/actions/getNetworkFromAddress.ts | 6 +- .../utils/buildEvmTransactionDataForNft.ts | 6 +- .../utils/buildEvmTransactionDataForToken.ts | 6 +- .../layer-2/utils/fetchIscAssetsForAccount.ts | 10 +- .../network/classes/base-evm-network.class.ts | 149 ------------------ .../core/network/classes/evm-network.class.ts | 146 ++++++++++++++++- .../core/network/classes/isc-chain.class.ts | 26 ++- .../network/classes/stardust-network.class.ts | 7 +- ...ault-isc-chains-configurations.constant.ts | 6 +- ...-l1-evm-network-configurations.constant.ts | 6 +- .../network/enums/evm-network-type.enum.ts | 4 - .../src/lib/core/network/enums/index.ts | 2 +- .../core/network/enums/network-type.enum.ts | 5 + .../interfaces/base-network.interface.ts | 3 +- .../evm-network-configuration.interface.ts | 8 +- .../interfaces/evm-network.interface.ts | 14 +- .../interfaces/stardust-network.interface.ts | 3 +- .../lib/core/network/stores/networks.store.ts | 4 +- .../core/network/types/evm-network.type.ts | 3 + .../src/lib/core/network/types/index.ts | 1 + .../lib/core/network/types/network.type.ts | 4 +- .../src/lib/core/network/utils/index.ts | 1 - .../src/lib/core/network/utils/isIscChain.ts | 7 - .../wallet/types/send-flow-parameter.type.ts | 1 + 28 files changed, 219 insertions(+), 228 deletions(-) delete mode 100644 packages/shared/src/lib/core/network/classes/base-evm-network.class.ts delete mode 100644 packages/shared/src/lib/core/network/enums/evm-network-type.enum.ts create mode 100644 packages/shared/src/lib/core/network/enums/network-type.enum.ts create mode 100644 packages/shared/src/lib/core/network/types/evm-network.type.ts delete mode 100644 packages/shared/src/lib/core/network/utils/isIscChain.ts diff --git a/packages/desktop/views/dashboard/drawers/network-config/views/NetworkInformationDrawer.svelte b/packages/desktop/views/dashboard/drawers/network-config/views/NetworkInformationDrawer.svelte index 3d21699ee9..a0c49aa00f 100644 --- a/packages/desktop/views/dashboard/drawers/network-config/views/NetworkInformationDrawer.svelte +++ b/packages/desktop/views/dashboard/drawers/network-config/views/NetworkInformationDrawer.svelte @@ -1,6 +1,6 @@