Skip to content
Merged
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
11 changes: 4 additions & 7 deletions apps/deploy-web/src/components/deployments/ManifestUpdate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import { LinkTo } from "@src/components/shared/LinkTo";
import ViewPanel from "@src/components/shared/ViewPanel";
import { useCertificate } from "@src/context/CertificateProvider";
import { useServices } from "@src/context/ServicesProvider";
import { useSettings } from "@src/context/SettingsProvider";
import { useWallet } from "@src/context/WalletProvider";
import { useProviderList } from "@src/queries/useProvidersQuery";
import { analyticsService } from "@src/services/analytics/analytics.service";
import networkStore from "@src/store/networkStore";
import type { DeploymentDto, LeaseDto } from "@src/types/deployment";
import type { ApiProviderList } from "@src/types/provider";
Expand Down Expand Up @@ -43,12 +41,11 @@ export const ManifestUpdate: React.FunctionComponent<Props> = ({
editedManifest,
onManifestChange
}) => {
const { providerProxy } = useServices();
const { providerProxy, analyticsService, chainApiHttpClient } = useServices();
const [parsingError, setParsingError] = useState<string | null>(null);
const [deploymentVersion, setDeploymentVersion] = useState<string | null>(null);
const [showOutsideDeploymentMessage, setShowOutsideDeploymentMessage] = useState(false);
const [isSendingManifest, setIsSendingManifest] = useState(false);
const { settings } = useSettings();
const { address, signAndBroadcastTx, isManaged: isManagedWallet } = useWallet();
const { data: providers } = useProviderList();
const { localCert, isLocalCertMatching } = useCertificate();
Expand Down Expand Up @@ -85,7 +82,7 @@ export const ManifestUpdate: React.FunctionComponent<Props> = ({
try {
if (!editedManifest) return null;

await deploymentData.NewDeploymentData(settings.apiEndpoint, yamlStr, dseq, address);
await deploymentData.NewDeploymentData(chainApiHttpClient, yamlStr, dseq, address);

setParsingError(null);
} catch (err: any) {
Expand All @@ -107,7 +104,7 @@ export const ManifestUpdate: React.FunctionComponent<Props> = ({
clearTimeout(timeoutId);
}
};
}, [editedManifest, deployment.dseq, settings.apiEndpoint, address]);
}, [editedManifest, deployment.dseq, chainApiHttpClient, address]);

function handleTextChange(value: string | undefined) {
onManifestChange(value || "");
Expand Down Expand Up @@ -143,7 +140,7 @@ export const ManifestUpdate: React.FunctionComponent<Props> = ({
try {
const doc = yaml.load(editedManifest);

const dd = await deploymentData.NewDeploymentData(settings.apiEndpoint, editedManifest, deployment.dseq, address); // TODO Flags
const dd = await deploymentData.NewDeploymentData(chainApiHttpClient, editedManifest, deployment.dseq, address); // TODO Flags
const mani = deploymentData.getManifest(doc, true);

// If it's actual update, send a transaction, else just send the manifest
Expand Down
2 changes: 1 addition & 1 deletion apps/deploy-web/src/components/home/YourAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export const YourAccount: React.FunctionComponent<Props> = ({ isLoadingBalances,

<div className="flex flex-wrap items-center gap-2">
{userProviders?.map(p => (
<Link key={p.owner} href={UrlService.providerDetailLeases(p.owner)}>
<Link key={p.owner} href={p.owner ? UrlService.providerDetailLeases(p.owner) : "#"}>
<Badge>{p.name}</Badge>
</Link>
))}
Expand Down
10 changes: 5 additions & 5 deletions apps/deploy-web/src/components/layout/TopBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function CreditCardBanner() {
function NetworkDownBanner() {
return (
<div className="fixed top-0 z-10 flex h-[40px] w-full items-center justify-center bg-primary px-3 py-2 md:space-x-4">
<span className="text-xs font-semibold text-white md:text-sm">The network is down. Unable to change deployments at the moment.</span>
<span className="text-xs font-semibold text-white md:text-sm">The blockchain is down. Console is in read-only mode.</span>
</div>
);
}
Expand All @@ -49,14 +49,14 @@ function MaintenanceBanner({ onClose }: { onClose: () => void }) {
export function TopBanner() {
const { isMaintenanceBannerOpen, setIsMaintenanceBannerOpen, isBlockchainDown, hasCreditCardBanner } = useTopBanner();

if (isMaintenanceBannerOpen) {
return <MaintenanceBanner onClose={() => setIsMaintenanceBannerOpen(false)} />;
}

if (isBlockchainDown) {
return <NetworkDownBanner />;
}

if (isMaintenanceBannerOpen) {
return <MaintenanceBanner onClose={() => setIsMaintenanceBannerOpen(false)} />;
}

if (hasCreditCardBanner) {
return <CreditCardBanner />;
}
Expand Down
60 changes: 30 additions & 30 deletions apps/deploy-web/src/components/layout/WalletStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,44 +35,44 @@ export function WalletStatus() {
<div className="w-full py-2">
<DropdownMenu modal={false} open={open}>
<DropdownMenuTrigger asChild>
{!!walletBalance && (
<div
className={cn("flex items-center justify-center rounded-md border px-4 py-2 text-sm", {
"border-primary bg-primary/10 text-primary dark:bg-primary dark:text-primary-foreground": isManaged,
"bg-background text-foreground": !isManaged
})}
onMouseOver={() => setOpen(true)}
>
<div className="flex items-center space-x-2" aria-label="Connected wallet name and balance">
{isManaged && isTrialing && <span className="text-xs">Trial</span>}
{!isManaged && (
<>
<Wallet className="text-xs" />
{walletName?.length > 20 ? (
<span className="text-xs">{getSplitText(walletName, 4, 4)}</span>
) : (
<span className="text-xs">{walletName}</span>
)}
</>
)}
</div>
<div
className={cn("flex items-center justify-center rounded-md border px-4 py-2 text-sm", {
"border-primary bg-primary/10 text-primary dark:bg-primary dark:text-primary-foreground": isManaged,
"bg-background text-foreground": !isManaged
})}
onMouseOver={() => setOpen(true)}
>
Comment on lines 36 to +44
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restore click/touch-open behavior for the wallet menu

By switching the trigger to onMouseOver only, the dropdown never opens on touch devices or via keyboard (no hover). Because the menu is controlled (open={open}) without onOpenChange, Radix can’t toggle it either, so wallet actions become inaccessible on mobile—this is a regression. Please reintroduce a click/pointer toggle (or wire onOpenChange={setOpen}) so the menu still opens outside of hover contexts.

<div className="flex items-center space-x-2" aria-label="Connected wallet name and balance">
{isManaged && isTrialing && <span className="text-xs">Trial</span>}
{!isManaged && (
<>
<Wallet className="text-xs" />
{walletName?.length > 20 ? (
<span className="text-xs">{getSplitText(walletName, 4, 4)}</span>
) : (
<span className="text-xs">{walletName}</span>
)}
</>
)}
</div>

{((isManaged && isTrialing) || !isManaged) && <div className="px-2">|</div>}
{walletBalance && ((isManaged && isTrialing) || !isManaged) && <div className="px-2">|</div>}

<div className="text-xs">
<div className="text-xs">
{walletBalance && (
<FormattedNumber
value={isManaged ? walletBalance.totalDeploymentGrantsUSD : walletBalance.totalUsd}
// eslint-disable-next-line react/style-prop-object
style="currency"
currency="USD"
/>
</div>
)}
</div>

<div>
<NavArrowDown className="ml-2 text-xs" />
</div>
<div>
<NavArrowDown className="ml-2 text-xs" />
</div>
)}
</div>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
Expand All @@ -86,8 +86,8 @@ export function WalletStatus() {
}}
>
<div>
{!isManaged && walletBalance && <CustodialWalletPopup walletBalance={walletBalance} />}
{withBilling && isManaged && walletBalance && <ManagedWalletPopup walletBalance={walletBalance} />}
{!isManaged && <CustodialWalletPopup walletBalance={walletBalance} />}
{withBilling && isManaged && <ManagedWalletPopup walletBalance={walletBalance} />}
</div>
</ClickAwayListener>
</DropdownMenuContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,7 @@ describe(CreateLease.name, () => {
});

await waitFor(() => {
expect((BidGroup as jest.Mock).mock.calls.length).toBeGreaterThan(0);
});
const bidGroupProps = (BidGroup as jest.Mock).mock.calls[0][0];
act(() => {
bidGroupProps.handleBidSelected(mapToBidDto(bids[0]));
});
await waitFor(() => {
expect(screen.queryByRole("button", { name: /Accept Bid/i })).toBeDisabled();
expect(screen.getByText(/Blockchain is down/i)).toBeInTheDocument();
});
});

Expand Down Expand Up @@ -435,6 +428,7 @@ describe(CreateLease.name, () => {
errorHandler: () => mock<AppDIContainer["errorHandler"]>(),
chainApiHttpClient: () =>
mock<AppDIContainer["chainApiHttpClient"]>({
isFallbackEnabled: !!input?.isBlockchainDown,
get: async url => {
if (url.includes("bids/list")) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,28 +451,38 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq, dependencies
</div>
)}

{!isLoadingBids && allClosed && (
{settings.isBlockchainDown && (
<div className="pt-4">
<d.Alert variant="warning">Blockchain is down. Please try to refresh the page or try again later.</d.Alert>
</div>
)}

{!settings.isBlockchainDown && !isLoadingBids && allClosed && (
<d.Button variant="default" color="secondary" onClick={handleCloseDeployment} size="sm" disabled={settings.isBlockchainDown}>
Close Deployment
</d.Button>
)}

{!zeroBidsForTrialWarningDisplayed && warningRequestsReached && !maxRequestsReached && (bids?.length || 0) === 0 && (
{!settings.isBlockchainDown && !zeroBidsForTrialWarningDisplayed && warningRequestsReached && !maxRequestsReached && (bids?.length || 0) === 0 && (
<div className="pt-4">
<d.Alert variant="warning">
There should be bids by now... You can wait longer in case a bid shows up or close the deployment and try again with a different configuration.
</d.Alert>
</div>
)}

{(isLoadingBids || (bids?.length || 0) === 0) && !maxRequestsReached && !isSendingManifest && !zeroBidsForTrialWarningDisplayed && (
<div className="flex flex-col items-center justify-center pt-4 text-center">
<d.Spinner size="large" />
<div className="pt-4">Waiting for bids...</div>
</div>
)}
{!settings.isBlockchainDown &&
(isLoadingBids || (bids?.length || 0) === 0) &&
!maxRequestsReached &&
!isSendingManifest &&
!zeroBidsForTrialWarningDisplayed && (
<div className="flex flex-col items-center justify-center pt-4 text-center">
<d.Spinner size="large" />
<div className="pt-4">Waiting for bids...</div>
</div>
)}

{!zeroBidsForTrialWarningDisplayed && maxRequestsReached && (bids?.length || 0) === 0 && (
{!settings.isBlockchainDown && !zeroBidsForTrialWarningDisplayed && maxRequestsReached && (bids?.length || 0) === 0 && (
<div className="pt-4">
<d.Alert variant="warning">
There's no bid for the current deployment. You can close the deployment and try again with a different configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { useSnackbar } from "notistack";

import { browserEnvConfig } from "@src/config/browser-env.config";
import { useCertificate } from "@src/context/CertificateProvider";
import { useSdlBuilder } from "@src/context/SdlBuilderProvider/SdlBuilderProvider";
import { useServices } from "@src/context/ServicesProvider";
Expand Down Expand Up @@ -74,7 +73,7 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({
const [sdlDenom, setSdlDenom] = useState("uakt");
const isAnonymousFreeTrialEnabled = useFlag("anonymous_free_trial");

const { analyticsService } = useServices();
const { analyticsService, chainApiHttpClient, appConfig } = useServices();
const { settings } = useSettings();
const { address, signAndBroadcastTx, isManaged, isTrialing, isOnboarding } = useWallet();
const router = useRouter();
Expand All @@ -87,7 +86,7 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({
const searchParams = useSearchParams();
const templateId = searchParams.get("templateId");
const { data: depositParams } = useDepositParams();
const defaultDeposit = depositParams || browserEnvConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT;
const defaultDeposit = depositParams || appConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT;
const wallet = useWallet();
const managedDenom = useManagedWalletDenom();
const { enqueueSnackbar } = useSnackbar();
Expand Down Expand Up @@ -166,7 +165,7 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({
try {
if (!yamlStr) return null;

const dd = await deploymentData.NewDeploymentData(settings.apiEndpoint, yamlStr, dseq, address, deposit, depositorAddress);
const dd = await deploymentData.NewDeploymentData(chainApiHttpClient, yamlStr, dseq, address, deposit, depositorAddress);
validateDeploymentData(dd, selectedTemplate);

setSdlDenom(dd.deposit.denom);
Expand Down Expand Up @@ -217,7 +216,7 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({
setIsCheckingPrerequisites(false);

if (isManaged) {
handleCreateClick(defaultDeposit, browserEnvConfig.NEXT_PUBLIC_MASTER_WALLET_ADDRESS);
handleCreateClick(defaultDeposit, appConfig.NEXT_PUBLIC_MASTER_WALLET_ADDRESS);
} else {
setIsDepositingDeployment(true);
}
Expand Down
10 changes: 4 additions & 6 deletions apps/deploy-web/src/components/sdl/RentGpusForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ import { Rocket } from "iconoir-react";
import { useAtom } from "jotai";
import { useRouter, useSearchParams } from "next/navigation";

import { browserEnvConfig } from "@src/config/browser-env.config";
import { useCertificate } from "@src/context/CertificateProvider";
import { useSettings } from "@src/context/SettingsProvider";
import { useServices } from "@src/context/ServicesProvider";
import { useWallet } from "@src/context/WalletProvider";
import { useManagedWalletDenom } from "@src/hooks/useManagedWalletDenom";
import { useWhen } from "@src/hooks/useWhen";
import { useGpuModels } from "@src/queries/useGpuQuery";
import { useDepositParams } from "@src/queries/useSaveSettings";
import type { TemplateOutputSummaryWithCategory } from "@src/queries/useTemplateQuery";
import { analyticsService } from "@src/services/analytics/analytics.service";
import sdlStore from "@src/store/sdlStore";
import type { ProfileGpuModelType, RentGpusFormValuesType, ServiceType } from "@src/types";
import { RentGpusFormValuesSchema } from "@src/types";
Expand Down Expand Up @@ -49,6 +47,7 @@ import { RegionSelect } from "./RegionSelect";
import { TokenFormControl } from "./TokenFormControl";

export const RentGpusForm: React.FunctionComponent = () => {
const { chainApiHttpClient, analyticsService, appConfig } = useServices();
const [error, setError] = useState<string | null>(null);
// const [templateMetadata, setTemplateMetadata] = useState<ITemplate>(null);
const [isQueryInit, setIsQuertInit] = useState(false);
Expand All @@ -70,14 +69,13 @@ export const RentGpusForm: React.FunctionComponent = () => {
const { services: _services } = watch();
const searchParams = useSearchParams();
const currentService: ServiceType = (_services && _services[0]) || ({} as any);
const { settings } = useSettings();
const { address, signAndBroadcastTx, isManaged } = useWallet();
const { loadValidCertificates, localCert, isLocalCertMatching, loadLocalCert, setSelectedCertificate } = useCertificate();
const [sdlDenom, setSdlDenom] = useState("uakt");
const router = useRouter();
const managedDenom = useManagedWalletDenom();
const { data: depositParams } = useDepositParams();
const defaultDeposit = depositParams || browserEnvConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT;
const defaultDeposit = depositParams || appConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT;

useWhen(isManaged && sdlDenom === "uakt", () => {
setSdlDenom(managedDenom);
Expand Down Expand Up @@ -135,7 +133,7 @@ export const RentGpusForm: React.FunctionComponent = () => {
try {
if (!yamlStr) return null;

const dd = await deploymentData.NewDeploymentData(settings.apiEndpoint, yamlStr, dseq, address, deposit, depositorAddress);
const dd = await deploymentData.NewDeploymentData(chainApiHttpClient, yamlStr, dseq, address, deposit, depositorAddress);
validateDeploymentData(dd);

setSdlDenom(dd.deposit.denom);
Expand Down
34 changes: 19 additions & 15 deletions apps/deploy-web/src/components/wallet/CustodialWalletPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { PriceValue } from "../shared/PriceValue";
import { ConnectManagedWalletButton } from "./ConnectManagedWalletButton";

interface CustodialWalletPopupProps extends React.PropsWithChildren {
walletBalance: WalletBalance;
walletBalance?: WalletBalance | null;
}

const withBilling = browserEnvConfig.NEXT_PUBLIC_BILLING_ENABLED;
Expand All @@ -43,22 +43,26 @@ export const CustodialWalletPopup: React.FC<CustodialWalletPopupProps> = ({ wall

<div className="mb-1 text-xs text-muted-foreground">Wallet Balance</div>
<div className="mb-4 rounded-md border border-success/10 bg-success/10 p-2 text-success dark:border-success/80 dark:bg-success/80 dark:text-foreground">
<div className="flex items-center justify-between space-x-2">
<span className="text-xs">AKT</span>
<span className="flex items-center space-x-1">
<PriceValue denom={UAKT_DENOM} value={uaktToAKT(walletBalance.totalUAKT, 2)} />
<span className="text-xs font-light">({uaktToAKT(walletBalance.totalUAKT, 2)} AKT)</span>
</span>
</div>
{(walletBalance && (
<>
<div className="flex items-center justify-between space-x-2">
<span className="text-xs">AKT</span>
<span className="flex items-center space-x-1">
<PriceValue denom={UAKT_DENOM} value={uaktToAKT(walletBalance.totalUAKT, 2)} />
<span className="text-xs font-light">({uaktToAKT(walletBalance.totalUAKT, 2)} AKT)</span>
</span>
</div>

<Separator className="my-2 bg-success/10 dark:bg-white/20" />
<Separator className="my-2 bg-success/10 dark:bg-white/20" />

<div className="flex items-center justify-between space-x-2">
<span className="text-xs">USDC</span>
<span>
<FormattedNumber value={udenomToDenom(walletBalance.totalUUSDC, 2)} style="currency" currency="USD" />
</span>
</div>
<div className="flex items-center justify-between space-x-2">
<span className="text-xs">USDC</span>
<span>
<FormattedNumber value={udenomToDenom(walletBalance.totalUUSDC, 2)} style="currency" currency="USD" />
</span>
</div>
</>
)) || <div className="space-x-2 text-xs text-white">Wallet Balance is unknown because the blockchain is down</div>}
</div>

<div className="text-xs text-muted-foreground">Wallet Actions</div>
Expand Down
Loading