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: migrate options and upload #108

Merged
merged 24 commits into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ff63719
feat: migrate options and upload
songwongtp Jan 19, 2023
2921ea4
fix: changelog
songwongtp Jan 19, 2023
2b878b2
Merge branch 'develop' into component/migrate-step1
songwongtp Jan 19, 2023
1bb7d37
fix: handle not admin case
songwongtp Jan 20, 2023
ca80ab0
Merge branch 'develop' into component/migrate-step1
songwongtp Jan 22, 2023
be68a48
fix: use useForm in upload section
songwongtp Jan 22, 2023
59aaf9a
feat: migration step 2
songwongtp Jan 23, 2023
9754107
feat: add validate code id
songwongtp Jan 24, 2023
e1407c5
Merge branch 'develop' into component/migrate-step2
songwongtp Jan 25, 2023
7478f4b
fix: stop migrate button from loading
songwongtp Jan 25, 2023
3222b91
fix: text
songwongtp Jan 25, 2023
19fb156
fix: as commented
songwongtp Jan 25, 2023
066bef3
fix: navigate to contract page after migrate
songwongtp Jan 26, 2023
a577a37
fix: navigate after clicking close
songwongtp Jan 26, 2023
2b1cd8e
Merge branch 'develop' into component/migrate-step1
songwongtp Jan 26, 2023
a0c5fec
Merge branch 'develop' into component/migrate-step1
songwongtp Jan 27, 2023
65d1622
Merge branch 'component/migrate-step1' into component/migrate-step2
songwongtp Jan 27, 2023
b6261a2
Merge pull request #120 from alleslabs/component/migrate-step2
songwongtp Jan 27, 2023
a797530
fix: as comments
songwongtp Jan 30, 2023
4292ceb
fix: upload access type
songwongtp Jan 30, 2023
5f57aa9
fix: as comments
songwongtp Jan 30, 2023
a18559c
Merge branch 'develop' into component/migrate-step1
songwongtp Jan 30, 2023
36a8fc5
fix: add span
songwongtp Jan 30, 2023
d5ae6db
Merge branch 'develop' into component/migrate-step1
evilpeach Jan 30, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#108](https://github.com/alleslabs/celatone-frontend/pull/108) Add migrate options on migrate page and upload new code for migration
- [#94](https://github.com/alleslabs/celatone-frontend/pull/94) Add unsupported assets in contract details page
- [#72](https://github.com/alleslabs/celatone-frontend/pull/72) Fix general wording and grammar
- [#110](https://github.com/alleslabs/celatone-frontend/pull/110) Fix proposal detail rendering
Expand Down
4 changes: 3 additions & 1 deletion src/lib/app-fns/tx/upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface UploadTxParams {
memo?: string;
client: SigningCosmWasmClient;
onTxSucceed?: (codeId: number) => void;
onMigrate: boolean;
}

export const uploadContractTx = ({
Expand All @@ -37,6 +38,7 @@ export const uploadContractTx = ({
memo,
client,
onTxSucceed,
onMigrate,
}: UploadTxParams): Observable<TxResultRendering> => {
return pipe(
sendingTx(fee),
Expand Down Expand Up @@ -88,7 +90,7 @@ export const uploadContractTx = ({
<Icon as={MdCloudUpload} fontSize="24px" color="text.dark" />
),
},
actionVariant: "upload",
actionVariant: onMigrate ? "upload-migrate" : "upload",
} as TxResultRendering;
}
)().pipe(catchTxError());
Expand Down
13 changes: 11 additions & 2 deletions src/lib/app-provider/tx/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export interface UploadStreamParams {
export const useUploadContractTx = (
wasmFileName: string | undefined,
wasmCode: Promise<ArrayBuffer> | undefined,
estimatedFee: StdFee | undefined
estimatedFee: StdFee | undefined,
onMigrate: boolean
) => {
const { address, getCosmWasmClient } = useWallet();

Expand All @@ -31,8 +32,16 @@ export const useUploadContractTx = (
fee: estimatedFee,
client,
onTxSucceed,
onMigrate,
});
},
[address, getCosmWasmClient, estimatedFee, wasmCode, wasmFileName]
[
address,
getCosmWasmClient,
estimatedFee,
wasmCode,
wasmFileName,
onMigrate,
]
);
};
2 changes: 1 addition & 1 deletion src/lib/components/forms/FormStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Icon, Spinner, Text } from "@chakra-ui/react";
import { MdCheckCircle, MdOutlineWarning } from "react-icons/md";

type ResponseState = "init" | "loading" | "success" | "error";
export type ResponseState = "init" | "loading" | "success" | "error";

export interface FormStatus {
state: ResponseState;
Expand Down
22 changes: 22 additions & 0 deletions src/lib/components/modal/tx/ButtonSection.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button, Icon } from "@chakra-ui/react";
import { useWallet } from "@cosmos-kit/react";
import { useRouter } from "next/router";
import { useCallback } from "react";
import { FiChevronRight } from "react-icons/fi";

Expand All @@ -18,6 +19,7 @@ export const ButtonSection = ({
onClose,
receipts,
}: ButtonSectionProps) => {
const router = useRouter();
const navigate = useInternalNavigate();
const { currentChainName } = useWallet();

Expand Down Expand Up @@ -64,6 +66,26 @@ export const ButtonSection = ({
</Button>
</>
);
case "upload-migrate":
return (
<Button
variant="primary"
rightIcon={
<Icon as={FiChevronRight} color="gray.900" fontSize="18px" />
}
onClick={() => {
const codeId = receipts.find((r) => r.title === "Code ID")?.value;

navigate({
pathname: "/migrate",
query: { contract: router.query.contract, "code-id": codeId },
});
onClose?.();
}}
>
Proceed to Migrate
</Button>
);
case "rejected":
case "resend":
return (
Expand Down
7 changes: 5 additions & 2 deletions src/lib/components/stepper/StepperItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Flex, Icon, Text } from "@chakra-ui/react";
import { MdCheck } from "react-icons/md";

import type { Step } from "./types";
import type { Mode, Step } from "./types";
import { StepperText } from "./types";

const StepLabel = ({
step,
Expand Down Expand Up @@ -33,9 +34,11 @@ const StepLabel = ({
};

export const StepperItem = ({
mode,
step,
currentStep,
}: {
mode: Mode;
step: Step;
currentStep: Step;
}) => {
Expand All @@ -61,7 +64,7 @@ export const StepperItem = ({
fontWeight={disabled ? 400 : 700}
color={disabled ? "text.disabled" : "text.main"}
>
{step === 1 ? "Upload or Select Code ID" : "Instantiate Code"}
{StepperText[mode][step - 1]}
</Text>
</Flex>
);
Expand Down
9 changes: 5 additions & 4 deletions src/lib/components/stepper/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Flex } from "@chakra-ui/react";

import { StepperItem } from "./StepperItem";
import type { Step } from "./types";
import type { Mode, Step } from "./types";

interface StepperProps {
mode: Mode;
currentStep: Step;
}

export const Stepper = ({ currentStep }: StepperProps) => {
export const Stepper = ({ mode, currentStep }: StepperProps) => {
return (
<Flex width="100%">
<StepperItem step={1} currentStep={currentStep} />
<StepperItem step={2} currentStep={currentStep} />
<StepperItem step={1} mode={mode} currentStep={currentStep} />
<StepperItem step={2} mode={mode} currentStep={currentStep} />
</Flex>
);
};
7 changes: 7 additions & 0 deletions src/lib/components/stepper/types.ts
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
export type Step = 1 | 2;

export type Mode = "deploy" | "migrate";

export const StepperText: Record<Mode, string[]> = {
deploy: ["Upload or Select Code ID", "Instantiate Code"],
migrate: ["Migrate Options", "Migrate Details"],
};
181 changes: 181 additions & 0 deletions src/lib/components/upload/UploadSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { Button, Flex, Icon } from "@chakra-ui/react";
import { useWallet } from "@cosmos-kit/react";
import { useCallback, useEffect } from "react";
import { useForm } from "react-hook-form";
import { FiChevronLeft } from "react-icons/fi";

import {
useFabricateFee,
useSimulateFee,
useUploadContractTx,
} from "lib/app-provider";
import { DropZone } from "lib/components/dropzone";
import { EstimatedFeeRender } from "lib/components/EstimatedFeeRender";
import { ControllerInput } from "lib/components/forms";
import {
getMaxCodeDescriptionLengthError,
MAX_CODE_DESCRIPTION_LENGTH,
} from "lib/data";
import { useCodeStore } from "lib/hooks";
import { useTxBroadcast } from "lib/providers/tx-broadcast";
import type { HumanAddr } from "lib/types";
import { AccessType, MsgType } from "lib/types";
import { composeMsg } from "lib/utils";

import { UploadCard } from "./components/UploadCard";
import type { UploadSectionState } from "./types";

interface UploadSectionProps {
handleBack: () => void;
onMigrate?: boolean;
}

export const UploadSection = ({
handleBack,
onMigrate = false,
}: UploadSectionProps) => {
const { simulate, loading } = useSimulateFee();
const fabricateFee = useFabricateFee();
const { address = "" } = useWallet();
const { broadcast } = useTxBroadcast();
const { updateCodeInfo } = useCodeStore();

const {
control,
watch,
setValue,
formState: { errors },
} = useForm<UploadSectionState>({
defaultValues: {
wasmFile: undefined,
codeDesc: "",
estimatedFee: undefined,
simulateStatus: "Pending",
simulateError: "",
},
mode: "all",
});
const { wasmFile, codeDesc, estimatedFee, simulateStatus, simulateError } =
watch();

const postUploadTx = useUploadContractTx(
wasmFile?.name,
wasmFile?.arrayBuffer(),
estimatedFee,
onMigrate
);

const proceed = useCallback(async () => {
const stream = await postUploadTx({
onTxSucceed: (codeId: number) => {
updateCodeInfo(
codeId,
address,
codeDesc || `${wasmFile?.name}(${codeId})`
);
},
codeDesc,
});

if (stream) broadcast(stream);
}, [
postUploadTx,
codeDesc,
broadcast,
updateCodeInfo,
address,
wasmFile?.name,
]);

useEffect(() => {
(async () => {
if (wasmFile) {
setValue("simulateStatus", "Pending");
setValue("simulateError", "");
const msg = composeMsg(MsgType.STORE_CODE, {
sender: address as HumanAddr,
wasmByteCode: new Uint8Array(await wasmFile.arrayBuffer()),
instantiatePermission: {
permission: AccessType.ACCESS_TYPE_ONLY_ADDRESS,
address: address as HumanAddr,
},
});
try {
const estimatedGasUsed = await simulate([msg]);
if (estimatedGasUsed) {
setValue("estimatedFee", fabricateFee(estimatedGasUsed));
setValue("simulateStatus", "Completed");
}
} catch (err) {
setValue("simulateStatus", "Failed");
setValue("simulateError", (err as Error).message);
}
}
})();
}, [wasmFile, address, simulate, fabricateFee, setValue]);

return (
<>
{wasmFile ? (
<UploadCard
file={wasmFile}
deleteFile={() => {
setValue("wasmFile", undefined);
setValue("estimatedFee", undefined);
}}
simulateStatus={simulateStatus}
simulateError={simulateError}
/>
) : (
<DropZone setFile={(file) => setValue("wasmFile", file)} />
)}
<ControllerInput
name="codeDesc"
control={control}
label="Code Description (Optional)"
helperText="Short description of your code. You can add or change this later."
rules={{
maxLength: MAX_CODE_DESCRIPTION_LENGTH,
}}
error={
errors.codeDesc && getMaxCodeDescriptionLengthError(codeDesc.length)
}
variant="floating"
my="32px"
/>
<Flex
fontSize="14px"
color="text.dark"
alignSelf="flex-start"
alignItems="center"
display="flex"
gap="4px"
>
Transaction Fee:{" "}
<EstimatedFeeRender estimatedFee={estimatedFee} loading={loading} />
</Flex>
<Flex justify="space-between" w="100%" mt="32px">
<Button
size="md"
variant="outline-gray"
w="128px"
leftIcon={
<Icon as={FiChevronLeft} color="text.dark" fontSize="18px" />
}
onClick={handleBack}
>
Back
</Button>
<Button
size="md"
variant="primary"
w="128px"
disabled={!estimatedFee || !wasmFile || !!errors.codeDesc}
onClick={proceed}
>
Upload
</Button>
</Flex>
</>
);
};
11 changes: 11 additions & 0 deletions src/lib/components/upload/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { StdFee } from "@cosmjs/stargate";

export type SimulateStatus = "Pending" | "Completed" | "Failed";

export interface UploadSectionState {
wasmFile?: File;
codeDesc: string;
estimatedFee?: StdFee;
simulateStatus: SimulateStatus;
simulateError: string;
}
2 changes: 1 addition & 1 deletion src/lib/pages/deploy/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Deploy = () => {
<Text variant="body1" color="text.dark" mb={3} fontWeight={700}>
DEPLOY NEW CONTRACT
</Text>
<Stepper currentStep={1} />
<Stepper mode="deploy" currentStep={1} />
<Heading as="h4" variant="h4" my="48px">
Select Deploy Option
</Heading>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/pages/instantiate/instantiate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => {
<Text variant="body1" color="text.dark" mb={3} fontWeight={700}>
DEPLOY NEW CONTRACT
</Text>
<Stepper currentStep={2} />
<Stepper mode="deploy" currentStep={2} />
<Heading as="h4" variant="h4" my="48px">
Instantiate new contract
</Heading>
Expand Down
Loading