Skip to content

Commit

Permalink
fix: add height check, and properly format releases
Browse files Browse the repository at this point in the history
  • Loading branch information
chalabi2 committed Jan 7, 2025
1 parent 12555f6 commit 8bd59d2
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 13 deletions.
93 changes: 81 additions & 12 deletions components/admins/modals/upgradeModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState, useMemo } from 'react';
import { createPortal } from 'react-dom';
import { cosmos } from '@liftedinit/manifestjs';
import { useTx, useFeeEstimation, useGitHubReleases, GitHubRelease } from '@/hooks';
import { useTx, useFeeEstimation, useGitHubReleases, GitHubRelease, useBlockHeight } from '@/hooks';
import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any';
import { MsgSoftwareUpgrade } from '@liftedinit/manifestjs/dist/codegen/cosmos/upgrade/v1beta1/tx';
import { Formik, Form } from 'formik';
Expand All @@ -27,18 +27,19 @@ interface UpgradeInfo {

const parseReleaseBody = (body: string): UpgradeInfo | null => {
try {
const nameMatch = body.match(/\*\*Upgrade Handler Name\*\*:\s*`([^`]+)`/);
const upgradeableMatch = body.match(/\*\*Upgradeable\*\*:\s*`([^`]+)`/);
const commitHashMatch = body.match(/\*\*Commit Hash\*\*:\s*`([^`]+)`/);
const nameMatch = body.match(/- \*\*Upgrade Handler Name\*\*: (.*?)(?:\r?\n|$)/);
const upgradeableMatch = body.match(/- \*\*Upgradeable\*\*: (.*?)(?:\r?\n|$)/);
const commitHashMatch = body.match(/- \*\*Commit Hash\*\*: (.*?)(?:\r?\n|$)/);

Check warning on line 32 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L30-L32

Added lines #L30 - L32 were not covered by tests

if (!nameMatch || !upgradeableMatch || !commitHashMatch) {
console.warn('Failed matches:', { nameMatch, upgradeableMatch, commitHashMatch });

Check warning on line 35 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L35

Added line #L35 was not covered by tests
return null;
}

return {
name: nameMatch[1],
upgradeable: upgradeableMatch[1].toLowerCase() === 'true',
commitHash: commitHashMatch[1],
name: nameMatch[1].trim(),
upgradeable: upgradeableMatch[1].trim().toLowerCase() === 'true',
commitHash: commitHashMatch[1].trim(),

Check warning on line 42 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L40-L42

Added lines #L40 - L42 were not covered by tests
};
} catch (error) {
console.error('Error parsing release body:', error);
Expand All @@ -47,13 +48,34 @@ const parseReleaseBody = (body: string): UpgradeInfo | null => {
};

const UpgradeSchema = Yup.object().shape({
height: Yup.number().required('Height is required').integer('Must be a valid number'),
height: Yup.number()
.typeError('Height must be a number')
.required('Height is required')
.integer('Must be a valid number')
.test(
'min-height',
'Height must be at least 1000 blocks above current height',
function (inputHeight) {
const proposedHeight = Number(inputHeight);
const chainHeight = Number(this.options.context?.chainData?.currentHeight || 0);

if (isNaN(proposedHeight) || isNaN(chainHeight)) {
return false;
}

const minimumAllowedHeight = chainHeight + 1000;

Check warning on line 67 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L57-L67

Added lines #L57 - L67 were not covered by tests
return proposedHeight >= minimumAllowedHeight;
}
),
});

export function UpgradeModal({ isOpen, onClose, admin, address, refetchPlan }: BaseModalProps) {
const [searchTerm, setSearchTerm] = useState('');
const { releases, isReleasesLoading } = useGitHubReleases();

const { blockHeight } = useBlockHeight();

Check warning on line 78 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L77-L78

Added lines #L77 - L78 were not covered by tests
// Filter releases that are upgradeable
const upgradeableReleases = useMemo(() => {
const allReleases = [...(releases || [])];
Expand Down Expand Up @@ -85,14 +107,41 @@ export function UpgradeModal({ isOpen, onClose, admin, address, refetchPlan }: B
const { tx, isSigning, setIsSigning } = useTx(env.chain);
const { estimateFee } = useFeeEstimation(env.chain);

const handleUpgrade = async (values: { name: string; height: string; info: string }) => {
const handleUpgrade = async (values: {
name: string;
height: string;
info: string;
selectedVersion: (GitHubRelease & { upgradeInfo?: UpgradeInfo | null }) | null;
}) => {

Check warning on line 115 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L110-L115

Added lines #L110 - L115 were not covered by tests
setIsSigning(true);

const selectedRelease = values.selectedVersion;
const binaryLinks: { [key: string]: string } = {};

// Map assets to their platform-specific links
selectedRelease?.assets?.forEach(asset => {
if (asset.name.includes('linux-amd64')) {
binaryLinks['linux/amd64'] = asset.browser_download_url;
} else if (asset.name.includes('linux-arm64')) {
binaryLinks['linux/arm64'] = asset.browser_download_url;
} else if (asset.name.includes('darwin-amd64')) {
binaryLinks['darwin/amd64'] = asset.browser_download_url;
} else if (asset.name.includes('darwin-arm64')) {
binaryLinks['darwin/arm64'] = asset.browser_download_url;
}
});

const infoObject = {
commitHash: values.selectedVersion?.upgradeInfo?.commitHash || '',
binaries: binaryLinks,
};

Check warning on line 138 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L117-L138

Added lines #L117 - L138 were not covered by tests
const msgUpgrade = softwareUpgrade({
plan: {
name: values.name,
height: BigInt(values.height),
time: new Date(0),
info: values.info,
info: JSON.stringify(infoObject),

Check warning on line 144 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L144

Added line #L144 was not covered by tests
},
authority: admin,
});
Expand Down Expand Up @@ -129,7 +178,14 @@ export function UpgradeModal({ isOpen, onClose, admin, address, refetchPlan }: B
info: '',
selectedVersion: null as (GitHubRelease & { upgradeInfo?: UpgradeInfo | null }) | null,
};

const validationContext = useMemo(
() => ({
chainData: {
currentHeight: Number(blockHeight),
},
}),
[blockHeight]
);

Check warning on line 188 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L181-L188

Added lines #L181 - L188 were not covered by tests
const modalContent = (
<dialog
className={`modal ${isOpen ? 'modal-open' : ''}`}
Expand All @@ -153,11 +209,22 @@ export function UpgradeModal({ isOpen, onClose, admin, address, refetchPlan }: B
<Formik
initialValues={initialValues}
validationSchema={UpgradeSchema}
validate={values => {
return UpgradeSchema.validate(values, { context: validationContext })
.then(() => ({}))
.catch(err => {
return err.errors.reduce((acc: { [key: string]: string }, curr: string) => {
acc[err.path] = curr;
return acc;
}, {});
});
}}

Check warning on line 221 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L212-L221

Added lines #L212 - L221 were not covered by tests
onSubmit={values => {
handleUpgrade({
name: values.selectedVersion?.upgradeInfo?.name || '',
height: values.height,
info: values.selectedVersion?.upgradeInfo?.commitHash || '',
selectedVersion: values.selectedVersion,

Check warning on line 227 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L227

Added line #L227 was not covered by tests
});
}}
validateOnChange={true}
Expand Down Expand Up @@ -266,11 +333,13 @@ export function UpgradeModal({ isOpen, onClose, admin, address, refetchPlan }: B
</div>
</div>
<TextInput
label="HEIGHT"
label={`HEIGHT (Current: ${blockHeight})`}

Check warning on line 336 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L336

Added line #L336 was not covered by tests
name="height"
type="number"

Check warning on line 338 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L338

Added line #L338 was not covered by tests
value={values.height}
onChange={handleChange}
placeholder="Block height for upgrade"
min="0"

Check warning on line 342 in components/admins/modals/upgradeModal.tsx

View check run for this annotation

Codecov / codecov/patch

components/admins/modals/upgradeModal.tsx#L342

Added line #L342 was not covered by tests
/>
<TextInput
label="NAME"
Expand Down
4 changes: 3 additions & 1 deletion components/react/inputs/BaseInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export const BaseInput: React.FC<BaseInputProps & React.InputHTMLAttributes<HTML
<div className="flex justify-between items-center">
{label && (
<label className="label" htmlFor={id}>
<span className="label-text text-[#00000099] dark:text-[#FFFFFF99]">{label}</span>
<span className="label-text text-[#00000099] dark:text-[#FFFFFF99] select-text">
{label}
</span>
</label>
)}
{helperText && (
Expand Down
24 changes: 24 additions & 0 deletions hooks/useQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,3 +958,27 @@ export const useGitHubReleases = () => {
refetchReleases: releasesQuery.refetch,
};
};

export const useBlockHeight = () => {
const { lcdQueryClient } = useLcdQueryClient();

const fetchBlockHeight = async () => {
const response = await lcdQueryClient?.cosmos.base.node.v1beta1.status();
return response?.height;
};

const blockHeightQuery = useQuery({
queryKey: ['blockHeight'],
queryFn: fetchBlockHeight,
enabled: !!lcdQueryClient,
staleTime: 0,
refetchInterval: 6000,
});

return {
blockHeight: blockHeightQuery.data,
isBlockHeightLoading: blockHeightQuery.isLoading,
isBlockHeightError: blockHeightQuery.isError,
refetchBlockHeight: blockHeightQuery.refetch,

Check warning on line 982 in hooks/useQueries.ts

View check run for this annotation

Codecov / codecov/patch

hooks/useQueries.ts#L962-L982

Added lines #L962 - L982 were not covered by tests
};
};

0 comments on commit 8bd59d2

Please sign in to comment.