diff --git a/libs/api/network-token/data-access/src/lib/api-network-token-data.service.ts b/libs/api/network-token/data-access/src/lib/api-network-token-data.service.ts index de862c1f..0ec1fca9 100644 --- a/libs/api/network-token/data-access/src/lib/api-network-token-data.service.ts +++ b/libs/api/network-token/data-access/src/lib/api-network-token-data.service.ts @@ -54,10 +54,10 @@ export class ApiNetworkTokenDataService { network: { connect: { cluster: network.cluster } }, type: NetworkTokenType.Validator, account: hash, - name: `${network.cluster.replace('Solana', 'Solana ')} Genesis`, + name: `${network.cluster.replace('Solana', 'Solana ')}`, + description: `Genesis Hash for ${network.cluster.replace('Solana', 'Solana ')}`, program: SystemProgram.programId.toBase58(), } - await this.core.data.networkToken.create({ data }) this.logger.log( `ensureGenesisHash: Created Genesis Block for cluster ${network.cluster} with genesis hash ${hash}`, @@ -89,6 +89,12 @@ export class ApiNetworkTokenDataService { async delete(networkTokenId: string) { await this.findOne(networkTokenId) + const conditions = await this.core.data.roleCondition.findMany({ + where: { token: { id: networkTokenId } }, + }) + if (conditions.length) { + throw new Error(`Network token ${networkTokenId} is used by ${conditions.length} role conditions`) + } const deleted = await this.core.data.networkToken.delete({ where: { id: networkTokenId } }) return !!deleted } diff --git a/libs/api/role/data-access/src/lib/api-role-resolver.service.ts b/libs/api/role/data-access/src/lib/api-role-resolver.service.ts index f365400a..d9e1080d 100644 --- a/libs/api/role/data-access/src/lib/api-role-resolver.service.ts +++ b/libs/api/role/data-access/src/lib/api-role-resolver.service.ts @@ -55,9 +55,8 @@ export class ApiRoleResolverService { const startedAt = Date.now() const conditions = await this.getRoleConditions({ community }) - const voteIdentities = await this.getVoteIdentities({ conditions }) - - await this.syncCommunityMembers({ communityId, voteIdentities }) + const clusterVoteIdentities = await this.getVoteIdentities({ conditions }) + await this.syncCommunityMembers({ communityId, voteIdentities: Object.values(clusterVoteIdentities).flat() }) const [roleMap, users] = await Promise.all([ this.getRoleMap({ community }), @@ -83,6 +82,7 @@ export class ApiRoleResolverService { // Now we want to loop over each condition and check the assets for (const condition of conditions) { + const voteIdentities = clusterVoteIdentities[condition.token.cluster] if (condition.token?.type === NetworkTokenType.Validator && voteIdentities.length) { if (voteIdentities.find((identity) => resolved.solanaIds.includes(identity))) { resolved.conditions.push(condition) @@ -128,29 +128,33 @@ export class ApiRoleResolverService { return Promise.resolve(result) } - async getVoteIdentities({ conditions }: { conditions: RoleCondition[] }) { + async getVoteIdentities({ conditions }: { conditions: RoleCondition[] }): Promise> { + const result: Record = { + [NetworkCluster.SolanaCustom]: [], + [NetworkCluster.SolanaDevnet]: [], + [NetworkCluster.SolanaMainnet]: [], + [NetworkCluster.SolanaTestnet]: [], + } const hasValidatorCondition: RoleCondition | undefined = conditions.find( (c) => c.type === NetworkTokenType.Validator, ) if (!hasValidatorCondition) { this.logger.debug(`getVoteIdentities: No validator conditions found.`) - return [] + return result } const clusters: NetworkCluster[] = conditions.map((c) => c.token.cluster) - const accounts: string[] = [] - for (const cluster of clusters) { try { const accountsForCluster = await this.network.cluster.getVoteIdentities(cluster) this.logger.debug(`[${cluster}] getVoteIdentities: Found ${accountsForCluster.length} identities.`) - accounts.push(...accountsForCluster) + result[cluster].push(...accountsForCluster) } catch (e) { this.logger.error(`[${cluster}] getVoteIdentities: Error getting vote identities for cluster.: ${e}`) } } - return accounts + return result } async syncCommunityMembers({ communityId, voteIdentities }: { communityId: string; voteIdentities: string[] }) { diff --git a/libs/web/bot/data-access/src/lib/use-admin-find-many-bot.ts b/libs/web/bot/data-access/src/lib/use-admin-find-many-bot.ts index 13723019..59e1199a 100644 --- a/libs/web/bot/data-access/src/lib/use-admin-find-many-bot.ts +++ b/libs/web/bot/data-access/src/lib/use-admin-find-many-bot.ts @@ -46,9 +46,15 @@ export function useAdminFindManyBot(props: Partial & { co return undefined }), deleteBot: (botId: string) => - sdk.adminDeleteBot({ botId }).then(() => { - toastSuccess('Bot deleted') - return query.refetch() - }), + sdk + .adminDeleteBot({ botId }) + .then(() => { + toastSuccess('Bot deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/community/data-access/src/lib/use-admin-find-many-community.ts b/libs/web/community/data-access/src/lib/use-admin-find-many-community.ts index d4dc97e9..8e802411 100644 --- a/libs/web/community/data-access/src/lib/use-admin-find-many-community.ts +++ b/libs/web/community/data-access/src/lib/use-admin-find-many-community.ts @@ -46,9 +46,15 @@ export function useAdminFindManyCommunity(props?: Partial - sdk.adminDeleteCommunity({ communityId }).then(() => { - toastSuccess('Community deleted') - return query.refetch() - }), + sdk + .adminDeleteCommunity({ communityId }) + .then(() => { + toastSuccess('Community deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/network-asset/data-access/src/lib/use-admin-find-many-network-asset.ts b/libs/web/network-asset/data-access/src/lib/use-admin-find-many-network-asset.ts index 13d0983d..f0e23aad 100644 --- a/libs/web/network-asset/data-access/src/lib/use-admin-find-many-network-asset.ts +++ b/libs/web/network-asset/data-access/src/lib/use-admin-find-many-network-asset.ts @@ -1,6 +1,6 @@ import { AdminFindManyNetworkAssetInput, NetworkCluster, NetworkTokenType } from '@pubkey-link/sdk' import { useSdk } from '@pubkey-link/web-core-data-access' -import { toastSuccess } from '@pubkey-ui/core' +import { toastError, toastSuccess } from '@pubkey-ui/core' import { useQuery } from '@tanstack/react-query' import { useState } from 'react' @@ -35,9 +35,15 @@ export function useAdminFindManyNetworkAsset( }, setSearch, deleteNetworkAsset: (networkAssetId: string) => - sdk.adminDeleteNetworkAsset({ networkAssetId }).then(() => { - toastSuccess('NetworkAsset deleted') - return query.refetch() - }), + sdk + .adminDeleteNetworkAsset({ networkAssetId }) + .then(() => { + toastSuccess('NetworkAsset deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/network-asset/feature/src/lib/user-network-asset-list.feature.tsx b/libs/web/network-asset/feature/src/lib/user-network-asset-list.feature.tsx index dc870e75..0a182cf1 100644 --- a/libs/web/network-asset/feature/src/lib/user-network-asset-list.feature.tsx +++ b/libs/web/network-asset/feature/src/lib/user-network-asset-list.feature.tsx @@ -65,7 +65,7 @@ export default function UserNetworkAssetListFeature({ {query.isLoading ? ( - ) : items?.length ? ( + ) : groups?.length ? ( {groups.map((group) => ( @@ -86,8 +86,19 @@ export default function UserNetworkAssetListFeature({ ))} ) : ( - + )} ) } + +function typeName(type: NetworkTokenType) { + switch (type) { + case NetworkTokenType.Fungible: + return 'tokens' + case NetworkTokenType.NonFungible: + return 'collectibles' + default: + return type + } +} diff --git a/libs/web/network-token/data-access/src/lib/use-admin-find-many-network-token.ts b/libs/web/network-token/data-access/src/lib/use-admin-find-many-network-token.ts index c7849acb..1c1c1db7 100644 --- a/libs/web/network-token/data-access/src/lib/use-admin-find-many-network-token.ts +++ b/libs/web/network-token/data-access/src/lib/use-admin-find-many-network-token.ts @@ -53,9 +53,15 @@ export function useAdminFindManyNetworkToken( return undefined }), deleteNetworkToken: (networkTokenId: string) => - sdk.adminDeleteNetworkToken({ networkTokenId }).then(() => { - toastSuccess('NetworkToken deleted') - return query.refetch() - }), + sdk + .adminDeleteNetworkToken({ networkTokenId }) + .then(() => { + toastSuccess('NetworkToken deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/network/data-access/src/lib/use-admin-find-many-network.ts b/libs/web/network/data-access/src/lib/use-admin-find-many-network.ts index bd9db334..cf70cfa6 100644 --- a/libs/web/network/data-access/src/lib/use-admin-find-many-network.ts +++ b/libs/web/network/data-access/src/lib/use-admin-find-many-network.ts @@ -46,9 +46,15 @@ export function useAdminFindManyNetwork(props?: Partial - sdk.adminDeleteNetwork({ networkId }).then(() => { - toastSuccess('Network deleted') - return query.refetch() - }), + sdk + .adminDeleteNetwork({ networkId }) + .then(() => { + toastSuccess('Network deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/role/data-access/src/lib/use-admin-find-many-role.ts b/libs/web/role/data-access/src/lib/use-admin-find-many-role.ts index a28782a4..a9e27939 100644 --- a/libs/web/role/data-access/src/lib/use-admin-find-many-role.ts +++ b/libs/web/role/data-access/src/lib/use-admin-find-many-role.ts @@ -46,9 +46,15 @@ export function useAdminFindManyRole(props: Partial & { return undefined }), deleteRole: (roleId: string) => - sdk.adminDeleteRole({ roleId }).then(() => { - toastSuccess('Role deleted') - return query.refetch() - }), + sdk + .adminDeleteRole({ roleId }) + .then(() => { + toastSuccess('Role deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/snapshot/data-access/src/lib/use-admin-find-many-snapshot.ts b/libs/web/snapshot/data-access/src/lib/use-admin-find-many-snapshot.ts index 8ffb629d..e30e4f2d 100644 --- a/libs/web/snapshot/data-access/src/lib/use-admin-find-many-snapshot.ts +++ b/libs/web/snapshot/data-access/src/lib/use-admin-find-many-snapshot.ts @@ -46,9 +46,15 @@ export function useAdminFindManySnapshot(props: Partial - sdk.adminDeleteSnapshot({ snapshotId }).then(() => { - toastSuccess('Snapshot deleted') - return query.refetch() - }), + sdk + .adminDeleteSnapshot({ snapshotId }) + .then(() => { + toastSuccess('Snapshot deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/user/data-access/src/lib/use-admin-find-many-user.ts b/libs/web/user/data-access/src/lib/use-admin-find-many-user.ts index 19164632..1545a0ef 100644 --- a/libs/web/user/data-access/src/lib/use-admin-find-many-user.ts +++ b/libs/web/user/data-access/src/lib/use-admin-find-many-user.ts @@ -1,6 +1,6 @@ import { AdminFindManyUserInput, UserRole, UserStatus } from '@pubkey-link/sdk' import { useSdk } from '@pubkey-link/web-core-data-access' -import { toastSuccess } from '@pubkey-ui/core' +import { toastError, toastSuccess } from '@pubkey-ui/core' import { useQuery } from '@tanstack/react-query' import { useState } from 'react' @@ -45,9 +45,15 @@ export function useAdminFindManyUser(props?: AdminFindManyUserInput) { setStatus(status) }, deleteUser: (userId: string) => - sdk.adminDeleteUser({ userId }).then(() => { - toastSuccess('User deleted') - return query.refetch() - }), + sdk + .adminDeleteUser({ userId }) + .then(() => { + toastSuccess('User deleted') + return query.refetch() + }) + .catch((err) => { + toastError(err.message) + return undefined + }), } } diff --git a/libs/web/user/feature/src/lib/user-profile-tab-communities.tsx b/libs/web/user/feature/src/lib/user-profile-tab-communities.tsx index f22a2c48..071dba98 100644 --- a/libs/web/user/feature/src/lib/user-profile-tab-communities.tsx +++ b/libs/web/user/feature/src/lib/user-profile-tab-communities.tsx @@ -11,7 +11,7 @@ export default function UserProfileTabCommunities({ isAuthUser, username }: { is ) : ( ) }