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: Delay of UI loading across all agents #805

Draft
wants to merge 10 commits into
base: staging
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import semver from 'semver';

import { CustomAlert } from '@/components/Alert';
import { ArrowUpRightSvg } from '@/components/custom-icons/ArrowUpRight';
import { FIVE_MINUTE_INTERVAL } from '@/constants/intervals';
import { DOWNLOAD_URL, GITHUB_API_LATEST_RELEASE } from '@/constants/urls';
import { useElectronApi } from '@/hooks/useElectronApi';

Expand All @@ -28,6 +29,7 @@ export const UpdateAvailableAlert = () => {

const appVersion = await getAppVersion();
if (!appVersion) return false;

const response = await fetch(GITHUB_API_LATEST_RELEASE);
if (!response.ok) return false;

Expand All @@ -47,7 +49,7 @@ export const UpdateAvailableAlert = () => {

return comparison === SemverComparisonResult.OUTDATED;
},
refetchInterval: 1000 * 60 * 5, // 5 minutes
refetchInterval: FIVE_MINUTE_INTERVAL,
});

if (!isFetched || !isPearlOutdated) {
Expand Down
6 changes: 4 additions & 2 deletions frontend/constants/intervals.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const ONE_MINUTE_INTERVAL = 60 * 1_000; // 1 minute

export const FIVE_SECONDS_INTERVAL = 5_000;

export const ONE_MINUTE_INTERVAL = 60 * 1_000;

export const FIVE_MINUTE_INTERVAL = 5 * ONE_MINUTE_INTERVAL;
3 changes: 0 additions & 3 deletions frontend/context/BalanceProvider/BalanceProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {

export const BalanceContext = createContext<{
isLoaded: boolean;
setIsLoaded: Dispatch<SetStateAction<boolean>>;
updateBalances: () => Promise<void>;
setIsPaused: Dispatch<SetStateAction<boolean>>;
walletBalances?: WalletBalance[];
Expand All @@ -48,7 +47,6 @@ export const BalanceContext = createContext<{
isPaused: boolean;
}>({
isLoaded: false,
setIsLoaded: () => {},
updateBalances: async () => {},
isPaused: false,
setIsPaused: () => {},
Expand Down Expand Up @@ -155,7 +153,6 @@ export const BalanceProvider = ({ children }: PropsWithChildren) => {
<BalanceContext.Provider
value={{
isLoaded,
setIsLoaded,
walletBalances,
stakedBalances,
updateBalances,
Expand Down
7 changes: 5 additions & 2 deletions frontend/context/BalancesAndRefillRequirementsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ export const BalancesAndRefillRequirementsProvider = ({
queryKey: REACT_QUERY_KEYS.BALANCES_AND_REFILL_REQUIREMENTS_KEY(
configId as string,
),
queryFn: () =>
BalanceService.getBalancesAndRefillRequirements(configId as string),
queryFn: ({ signal }) =>
BalanceService.getBalancesAndRefillRequirements({
serviceConfigId: configId!,
signal,
}),
enabled: !!configId && isUserLoggedIn && isOnline,
refetchInterval,
});
Expand Down
2 changes: 1 addition & 1 deletion frontend/context/MasterWalletProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const MasterWalletProvider = ({ children }: PropsWithChildren) => {
isFetched,
} = useQuery({
queryKey: REACT_QUERY_KEYS.WALLETS_KEY,
queryFn: WalletService.getWallets,
queryFn: ({ signal }) => WalletService.getWallets(signal),
refetchInterval: isOnline && !paused ? FIVE_SECONDS_INTERVAL : false,
select: (data) =>
transformMiddlewareWalletResponse(data).filter(
Expand Down
9 changes: 6 additions & 3 deletions frontend/context/ServicesProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const ServicesProvider = ({ children }: PropsWithChildren) => {
refetch,
} = useQuery<MiddlewareServiceResponse[]>({
queryKey: REACT_QUERY_KEYS.SERVICES_KEY,
queryFn: ServicesService.getServices,
queryFn: ({ signal }) => ServicesService.getServices(signal),
enabled: isOnline && !paused,
refetchInterval: FIVE_SECONDS_INTERVAL,
});
Expand All @@ -112,8 +112,11 @@ export const ServicesProvider = ({ children }: PropsWithChildren) => {
queryKey: REACT_QUERY_KEYS.SERVICE_DEPLOYMENT_STATUS_KEY(
selectedServiceConfigId,
),
queryFn: () =>
ServicesService.getDeployment(selectedServiceConfigId as string),
queryFn: ({ signal }) =>
ServicesService.getDeployment({
serviceConfigId: selectedServiceConfigId!,
signal,
}),
enabled: isOnline && !!selectedServiceConfigId,
refetchInterval: FIVE_SECONDS_INTERVAL,
});
Expand Down
34 changes: 19 additions & 15 deletions frontend/hooks/useService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ export const useService = (serviceConfigId?: string) => {
const { services, isFetched: isLoaded, selectedService } = useServices();

const service = useMemo<Optional<Service>>(() => {
if (serviceConfigId === selectedService?.service_config_id)
if (serviceConfigId === selectedService?.service_config_id) {
return selectedService;
}

return services?.find(
(service) => service.service_config_id === serviceConfigId,
);
Expand Down Expand Up @@ -104,6 +106,10 @@ export const useService = (serviceConfigId?: string) => {
return addressesByChainId;
}, [service]);

/**
* Flat list of all addresses associated with the service.
* ie, all agentSafe and agentEoas
*/
const flatAddresses = useMemo(() => {
if (!service) return [];
if (!addresses) return [];
Expand All @@ -116,24 +122,22 @@ export const useService = (serviceConfigId?: string) => {
}, [addresses, service]);

const serviceSafes = useMemo(() => {
return (
serviceWallets?.filter(
(wallet): wallet is AgentSafe =>
flatAddresses.includes(wallet.address) &&
wallet.owner === WalletOwnerType.Agent &&
wallet.type === WalletType.Safe,
) ?? []
if (!serviceWallets) return [];
return serviceWallets.filter(
(wallet): wallet is AgentSafe =>
flatAddresses.includes(wallet.address) &&
wallet.owner === WalletOwnerType.Agent &&
wallet.type === WalletType.Safe,
);
}, [flatAddresses, serviceWallets]);

const serviceEoa = useMemo(() => {
return (
serviceWallets?.find(
(wallet): wallet is AgentEoa =>
flatAddresses.includes(wallet.address) &&
wallet.owner === WalletOwnerType.Agent &&
wallet.type === WalletType.EOA,
) ?? null
if (!serviceWallets) return null;
return serviceWallets.find(
(wallet): wallet is AgentEoa =>
flatAddresses.includes(wallet.address) &&
wallet.owner === WalletOwnerType.Agent &&
wallet.type === WalletType.EOA,
);
}, [flatAddresses, serviceWallets]);

Expand Down
12 changes: 3 additions & 9 deletions frontend/service/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import { BACKEND_URL } from '@/constants/urls';
*/
const getAccount = () =>
fetch(`${BACKEND_URL}/account`, {
headers: {
...CONTENT_TYPE_JSON_UTF8,
},
headers: { ...CONTENT_TYPE_JSON_UTF8 },
}).then((res) => {
if (res.ok) return res.json();
throw new Error('Failed to get account');
Expand All @@ -20,9 +18,7 @@ const getAccount = () =>
const createAccount = (password: string) =>
fetch(`${BACKEND_URL}/account`, {
method: 'POST',
headers: {
...CONTENT_TYPE_JSON_UTF8,
},
headers: { ...CONTENT_TYPE_JSON_UTF8 },
body: JSON.stringify({ password }),
}).then((res) => {
if (res.ok) return res.json();
Expand Down Expand Up @@ -52,9 +48,7 @@ const loginAccount = (password: string) =>
fetch(`${BACKEND_URL}/account/login`, {
method: 'POST',
headers: { ...CONTENT_TYPE_JSON_UTF8 },
body: JSON.stringify({
password,
}),
body: JSON.stringify({ password }),
}).then((res) => {
if (res.ok) return res.json();
throw new Error('Failed to login');
Expand Down
38 changes: 26 additions & 12 deletions frontend/service/Services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ import { asEvmChainId } from '@/utils/middlewareHelpers';
/**
* Get a single service from the backend
*/
const getService = async (
serviceConfigId: string,
): Promise<MiddlewareServiceResponse> =>
const getService = async ({
serviceConfigId,
signal,
}: {
serviceConfigId: ServiceConfigId;
signal: AbortSignal;
}): Promise<MiddlewareServiceResponse> =>
fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, {
method: 'GET',
headers: { ...CONTENT_TYPE_JSON_UTF8 },
signal,
}).then((response) => {
if (response.ok) {
return response.json();
Expand All @@ -32,14 +37,15 @@ const getService = async (
* Gets an array of services from the backend
* @returns An array of services
*/
const getServices = async (): Promise<MiddlewareServiceResponse[]> =>
const getServices = async (
signal: AbortSignal,
): Promise<MiddlewareServiceResponse[]> =>
fetch(`${BACKEND_URL_V2}/services`, {
method: 'GET',
headers: { ...CONTENT_TYPE_JSON_UTF8 },
signal,
}).then((response) => {
if (response.ok) {
return response.json();
}
if (response.ok) return response.json();
throw new Error('Failed to fetch services');
});

Expand Down Expand Up @@ -143,15 +149,23 @@ const stopDeployment = async (
throw new Error('Failed to stop deployment');
});

const getDeployment = async (serviceConfigId: string): Promise<Deployment> =>
/**
* To get the deployment of a service
*/
const getDeployment = async ({
serviceConfigId,
signal,
}: {
serviceConfigId: ServiceConfigId;
signal: AbortSignal;
}): Promise<Deployment> =>
fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}/deployment`, {
method: 'GET',
headers: { ...CONTENT_TYPE_JSON_UTF8 },
signal,
}).then((response) => {
if (response.ok) {
return response.json();
}
throw new Error('Failed to get deployment');
if (response.ok) return response.json();
throw new Error('Failed to fetch deployment');
});

/**
Expand Down
20 changes: 8 additions & 12 deletions frontend/service/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import { BACKEND_URL } from '@/constants/urls';
/**
* Returns a list of available wallets
*/
const getWallets = async () =>
fetch(`${BACKEND_URL}/wallet`).then((res) => {
const getWallets = async (signal: AbortSignal) =>
fetch(`${BACKEND_URL}/wallet`, {
signal,
}).then((res) => {
if (res.ok) return res.json();
throw new Error('Failed to get wallets');
throw new Error('Failed to fetch wallets');
}) as Promise<MiddlewareWalletResponse[]>;

const createEoa = async () =>
fetch(`${BACKEND_URL}/wallet`, {
method: 'POST',
headers: {
...CONTENT_TYPE_JSON_UTF8,
},
headers: { ...CONTENT_TYPE_JSON_UTF8 },
body: JSON.stringify({ ledger_type: 'ethereum' }),
}).then((res) => {
if (res.ok) return res.json();
Expand All @@ -26,9 +26,7 @@ const createEoa = async () =>
const createSafe = async (chain: MiddlewareChain, backup_owner?: string) =>
fetch(`${BACKEND_URL}/wallet/safe`, {
method: 'POST',
headers: {
...CONTENT_TYPE_JSON_UTF8,
},
headers: { ...CONTENT_TYPE_JSON_UTF8 },
body: JSON.stringify({ chain, backup_owner, fund_amount: 0 }),
}).then((res) => {
if (res.ok) return res.json();
Expand All @@ -41,9 +39,7 @@ const updateSafeBackupOwner = async (
) =>
fetch(`${BACKEND_URL}/wallet/safe`, {
method: 'PUT',
headers: {
...CONTENT_TYPE_JSON_UTF8,
},
headers: { ...CONTENT_TYPE_JSON_UTF8 },
body: JSON.stringify({ chain, backup_owner }),
}).then((res) => {
if (res.ok) return res.json();
Expand Down
13 changes: 9 additions & 4 deletions frontend/service/balances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@ import { BACKEND_URL_V2 } from '@/constants/urls';
/**
* API call to get balances and refill requirements
*/
const getBalancesAndRefillRequirements = async (
serviceConfigId: string,
): Promise<BalancesAndFundingRequirements> => {
const getBalancesAndRefillRequirements = async ({
serviceConfigId,
signal,
}: {
serviceConfigId: string;
signal: AbortSignal;
}): Promise<BalancesAndFundingRequirements> => {
return fetch(
`${BACKEND_URL_V2}/service/${serviceConfigId}/refill_requirements`,
{
method: 'GET',
headers: { ...CONTENT_TYPE_JSON_UTF8 },
signal,
},
).then((response) => {
if (response.ok) {
return response.json();
}
throw new Error(
`Failed to balances and refill requirements for ${serviceConfigId}`,
`Failed to fetch balances and refill requirements for ${serviceConfigId}`,
);
});
};
Expand Down