Skip to content

Commit 41a58d2

Browse files
authored
feat(tangle-cloud): Service Management Flow (#3034)
1 parent 0534993 commit 41a58d2

File tree

66 files changed

+1957
-953
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1957
-953
lines changed

apps/leaderboard/src/features/leaderboard/components/LeaderboardTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export const LeaderboardTable = () => {
204204
});
205205

206206
// TODO: Add network tabs when we support both mainnet and testnet
207-
const [networkTab] = useState<NetworkType>('TESTNET');
207+
const [networkTab] = useState<NetworkType>('TESTNET' as NetworkType);
208208

209209
const {
210210
data: latestBlock,

apps/leaderboard/src/features/leaderboard/utils/processLeaderboardRecord.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ZERO_BIG_INT } from '@tangle-network/dapp-config/constants';
22
import type { IdentityType } from '@tangle-network/tangle-shared-ui/utils/polkadot/identity';
3+
import { NetworkType } from '@tangle-network/tangle-shared-ui/graphql/graphql';
34
import { toBigInt } from '@tangle-network/ui-components';
45
import find from 'lodash/find';
56
import findLast from 'lodash/findLast';
@@ -251,6 +252,6 @@ export const processLeaderboardRecord = (
251252
lastUpdatedAtTimestamp: record.lastUpdatedAtTimestamp,
252253
identity,
253254
// TODO: This should fetch from the API once the server supports multi-chain
254-
network: 'TESTNET',
255+
network: 'TESTNET' as NetworkType,
255256
} satisfies Account;
256257
};

apps/tangle-cloud/src/components/InstanceHeader.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,27 @@ const InstanceHeader: FC<Props> = ({ title, githubPath, creator }) => {
1313
return (
1414
<div
1515
className={twMerge(
16-
'flex gap-3 p-6 w-full border-2 border-mono-170',
17-
'bg-gradient-to-b from-blue-120/20 to-blue-100/20',
18-
'before:bg-gradient-to-b before:from-mono-170/50 before:to-mono-170/30',
16+
'flex gap-3 p-6 w-full border-2',
17+
'border-mono-80 dark:border-mono-170',
18+
'bg-gradient-to-b from-blue-120/10 to-blue-100/10 dark:from-blue-120/20 dark:to-blue-100/20',
19+
'before:bg-gradient-to-b before:from-mono-80/40 before:to-mono-80/20 dark:before:from-mono-170/50 dark:before:to-mono-170/30',
1920
)}
2021
>
2122
<div className="flex flex-col gap-2">
22-
<Typography variant="h5" className="flex items-center gap-2">
23+
<Typography
24+
variant="h5"
25+
className="flex items-center gap-2 text-mono-200 dark:text-mono-0"
26+
>
2327
{title}{' '}
2428
{githubPath && (
2529
<GithubFill size="lg" target="_blank" href={githubPath} />
2630
)}
2731
</Typography>
2832

29-
<Typography variant="body1" className="!text-mono-100">
33+
<Typography
34+
variant="body1"
35+
className="text-mono-140 dark:text-mono-100"
36+
>
3037
{creator}
3138
</Typography>
3239
</div>

apps/tangle-cloud/src/constants/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export enum TxName {
33
REJECT_SERVICE_REQUEST = 'reject service request',
44
APPROVE_SERVICE_REQUEST = 'approve service request',
55
DEPLOY_BLUEPRINT = 'deploy blueprint',
6+
TERMINATE_SERVICE_INSTANCE = 'terminate service instance',
67
}
78

89
export enum SessionStorageKey {

apps/tangle-cloud/src/data/operators/useOperatorStatsData.ts

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ import { SubstrateAddress } from '@tangle-network/ui-components/types/address';
44
import { useCallback, useMemo } from 'react';
55
import { catchError, combineLatest, map, of } from 'rxjs';
66
import { z } from 'zod';
7+
import { StorageKey, u64 } from '@polkadot/types';
8+
import { toSubstrateAddress } from '@tangle-network/ui-components/utils/toSubstrateAddress';
9+
import useNetworkStore from '@tangle-network/tangle-shared-ui/context/useNetworkStore';
10+
import { Option } from '@polkadot/types';
11+
import {
12+
TanglePrimitivesServicesService,
13+
TanglePrimitivesServicesServiceServiceBlueprint,
14+
TanglePrimitivesServicesServiceServiceRequest,
15+
TanglePrimitivesServicesTypesOperatorProfile,
16+
} from '@polkadot/types/lookup';
17+
import { ITuple } from '@polkadot/types/types';
18+
import { AccountId32 } from '@polkadot/types/interfaces';
719

820
const operatorStatsSchema = z.object({
921
registeredBlueprints: z.number().default(0),
@@ -18,6 +30,8 @@ const operatorStatsSchema = z.object({
1830
export const useOperatorStatsData = (
1931
operatorAddress: SubstrateAddress | null | undefined,
2032
) => {
33+
const { network } = useNetworkStore();
34+
2135
const { result: operatorStats, ...rest } = useApiRx(
2236
useCallback(
2337
(apiRx) => {
@@ -30,14 +44,17 @@ export const useOperatorStatsData = (
3044
? of({})
3145
: apiRx.query.services?.operatorsProfile(operatorAddress).pipe(
3246
map((operatorProfile) => {
33-
if (operatorProfile.isNone) {
47+
const unwrapped = (
48+
operatorProfile as Option<TanglePrimitivesServicesTypesOperatorProfile>
49+
).unwrapOr(null);
50+
51+
if (unwrapped === null) {
3452
return {};
3553
}
3654

37-
const detailed = operatorProfile.unwrap();
3855
return {
39-
registeredBlueprints: detailed.blueprints.strings.length,
40-
runningServices: detailed.services.strings.length,
56+
registeredBlueprints: unwrapped.blueprints.size,
57+
runningServices: unwrapped.services.size,
4158
};
4259
}),
4360
catchError((error) => {
@@ -56,18 +73,39 @@ export const useOperatorStatsData = (
5673
map((serviceRequests) => {
5774
const pendingServices = serviceRequests.filter(
5875
([requestId, serviceRequest]) => {
59-
if (serviceRequest.isNone) {
76+
const unwrapped = (
77+
serviceRequest as Option<TanglePrimitivesServicesServiceServiceRequest>
78+
).unwrapOr(null);
79+
80+
if (unwrapped === null) {
6081
return false;
6182
}
6283

6384
const primitiveServiceRequest = toPrimitiveServiceRequest(
64-
requestId,
65-
serviceRequest.unwrap(),
85+
requestId as StorageKey<[u64]>,
86+
unwrapped,
6687
);
6788
return primitiveServiceRequest.operatorsWithApprovalState.some(
68-
(operator) =>
69-
operator.operator === operatorAddress &&
70-
operator.approvalStateStatus === 'Pending',
89+
(operator) => {
90+
const normalizedChainOperator = toSubstrateAddress(
91+
operator.operator,
92+
network.ss58Prefix,
93+
);
94+
const normalizedCurrentOperator = operatorAddress
95+
? toSubstrateAddress(
96+
operatorAddress,
97+
network.ss58Prefix,
98+
)
99+
: null;
100+
101+
const addressMatch =
102+
normalizedChainOperator ===
103+
normalizedCurrentOperator;
104+
const statusMatch =
105+
operator.approvalStateStatus === 'Pending';
106+
107+
return addressMatch && statusMatch;
108+
},
71109
);
72110
},
73111
);
@@ -90,13 +128,24 @@ export const useOperatorStatsData = (
90128
: apiRx.query.services?.blueprints?.entries().pipe(
91129
map((blueprints) => {
92130
const publishedBlueprints = blueprints.filter(
93-
([_, optBlueprint]) => {
94-
if (optBlueprint.isNone) {
131+
([, optBlueprint]) => {
132+
const unwrapped = (
133+
optBlueprint as Option<
134+
ITuple<
135+
[
136+
AccountId32,
137+
TanglePrimitivesServicesServiceServiceBlueprint,
138+
]
139+
>
140+
>
141+
).unwrapOr(null);
142+
143+
if (unwrapped === null) {
95144
return false;
96145
}
97146

98-
const blueprint = optBlueprint.unwrap();
99-
const publisher = blueprint[0].toHuman();
147+
const owner = unwrapped[0];
148+
const publisher = owner.toHuman();
100149
return publisher === operatorAddress;
101150
},
102151
);
@@ -120,11 +169,13 @@ export const useOperatorStatsData = (
120169
: apiRx.query.services?.instances.entries().pipe(
121170
map((instances) => {
122171
const deployedServices = instances.filter(([_, instance]) => {
123-
if (instance.isNone) {
172+
const unwrapped = (
173+
instance as Option<TanglePrimitivesServicesService>
174+
).unwrapOr(null);
175+
if (unwrapped === null) {
124176
return false;
125177
}
126-
const detailed = instance.unwrap();
127-
return detailed.owner.toHuman() === operatorAddress;
178+
return unwrapped.owner.toHuman() === operatorAddress;
128179
});
129180
return {
130181
deployedServices: deployedServices.length,
@@ -162,7 +213,7 @@ export const useOperatorStatsData = (
162213
),
163214
);
164215
},
165-
[operatorAddress],
216+
[operatorAddress, network.ss58Prefix],
166217
),
167218
);
168219

0 commit comments

Comments
 (0)