Skip to content
Open
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
2 changes: 1 addition & 1 deletion app/components/AccountModule/screens/ScreenConnecting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { GU, textStyle, useTheme } from "@blossom-labs/rosette-ui";
import styled from "styled-components";

import { getWalletIconPath } from "../helpers";
import { LoadingRing } from "../LoadingRing";
import { LoadingRing } from "../../LoadingRing";
import { useAccounModuleStore } from "../use-account-module-store";

export const ScreenConnecting = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GU, textStyle } from "@blossom-labs/rosette-ui/";
import styled from "styled-components";

import { LoadingRing } from "../LoadingRing";
import { LoadingRing } from "../../LoadingRing";
import { useAccounModuleStore } from "../use-account-module-store";

export const ScreenPromptedAction = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TextInput,
Header,
textStyle,
Info,
} from "@blossom-labs/rosette-ui";
import { forwardRef, memo, useCallback, useState } from "react";
import type {
Expand All @@ -21,6 +22,8 @@ import { actions } from "../use-contract-descriptor-store";
import type { Function } from "../use-contract-descriptor-store";
import { DescriptionField } from "./DescriptionField";
import { canTab, getSelectionRange } from "~/utils/client/selection.client";
import { useTxDescribe } from "@blossom-labs/rosette-react";
import { constants } from "ethers";

type FunctionDescriptorProps = {
fnDescriptorEntry: Function;
Expand All @@ -33,6 +36,7 @@ export const FunctionDescriptor = memo(
({ fnDescriptorEntry, description, onEntryChange, ...props }, ref) => {
const [showModal, setShowModal] = useState(false);
const [callData, setCallData] = useState("");
const [testDescriptionError, setTestDescriptionError] = useState("");
const entry = fnDescriptorEntry.entry;
const { notice, status } = entry || {};
const descriptorStatus = status || FnDescriptionStatus.Available;
Expand Down Expand Up @@ -69,7 +73,14 @@ export const FunctionDescriptor = memo(
setShowModal(true);
};

const handleDescribeCalldata = () => {};
const handleDescribeCalldata = useCallback( () => {
useTxDescribe({
to: constants.AddressZero,
data: callData
})
setTestDescriptionError()
},[]);


return (
<Container>
Expand Down Expand Up @@ -109,6 +120,7 @@ export const FunctionDescriptor = memo(
wide
/>
</Field>
<Info></Info>
<Button
label="Test"
wide
Expand Down
46 changes: 24 additions & 22 deletions app/components/ContractDescriptorScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect } from "react";
import { useCallback, useEffect, useState } from "react";
import { useAccount } from "wagmi";
import { utils } from "ethers";
import { Button, GU, useViewport } from "@blossom-labs/rosette-ui";
Expand All @@ -22,6 +22,8 @@ import { HelperFunctionsPicker } from "./HelperFunctionsPicker";
import { FnDescriptorsCarousel } from "./FnDescriptorsCarousel";
import type { IPFSFnDescription } from "~/routes/fn-descriptions-upload";
import debounce from "lodash.debounce";
import MultiModal from "../MultiModal/MultiModal";
import SubmitEntriesScreens from "../ModalFlows/SubmitEntriesScreens";

const FN_DESCRIPTOR_HEIGHT = "527px";

Expand Down Expand Up @@ -54,6 +56,8 @@ export const ContractDescriptorScreen = ({
contractData: { abi, bytecode },
currentFnEntries,
}: ContractDescriptorScreenProps) => {
const [modalVisible, setModalVisible] = useState(false);
const [modalMode, setModalMode] = useState(null);
const { below } = useViewport();
const [{ data: accountData }] = useAccount();
const { fnSelected, fnDescriptorEntries, userFnDescriptions } =
Expand All @@ -65,27 +69,18 @@ export const ContractDescriptorScreen = ({
const actionFetcher = useFetcher();
const { upsertEntries } = useRosetteActions();

const handleSubmit = useCallback(
(event) => {
event.preventDefault();

const fnDescriptionsJSON = buildUploadDataJSON(
fnDescriptorEntries,
userFnDescriptions
);

actionFetcher.submit(
{
fnDescriptions: JSON.stringify(fnDescriptionsJSON),
},
{
method: "post",
action: "/fn-descriptions-upload",
}
);
},
[actionFetcher, fnDescriptorEntries, userFnDescriptions]
);
const handleHideModal = useCallback(() => {
setModalVisible(false);
}, []);

const handleShowModal = useCallback((mode) => {
setModalVisible(true);
setModalMode(mode);
}, []);

const handleSubmit = useCallback(() => {
handleShowModal("submit");
}, [handleShowModal]);

useEffect(() => {
const submitEntries = async () => {
Expand Down Expand Up @@ -176,6 +171,13 @@ export const ContractDescriptorScreen = ({
disabled={!accountData?.address || fnDescriptionsCounter === 0}
/>
</SubmitContainer>
<MultiModal
visible={modalVisible}
onClose={handleHideModal}
onClosed={() => setModalMode(null)}
>
{modalMode === "Submit" && <SubmitEntriesScreens />}
</MultiModal>
</Layout>
</form>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled, { keyframes } from "styled-components";

import loadingRing from "./assets/loading-ring.svg";
import loadingRing from "~/assets/loading-ring.svg";

const spin = keyframes`
from {
Expand Down
192 changes: 192 additions & 0 deletions app/components/ModalFlows/ModalFlowBase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import React, { useEffect, useMemo } from "react";
import { useSigner } from "wagmi";

import { LoadingRing } from "../LoadingRing";
import { useMultiModal } from "../MultiModal/MultiModalProvider";
import MultiModalScreens from "../MultiModal/MultiModalScreens";
import Stepper from "../Stepper/Stepper";

// import { useActivity } from '@providers/ActivityProvider'

const INDEX_NUMBER = ["First", "Second", "Third", "Fourth", "Fifth"];

type ModalFlowBaseType = {
loading: boolean;
screens: Array<any>;
transactions: Array<any>;
onComplete: () => void;
onCompleteActions: any;
frontLoad?: boolean;
transactionTitle?: string;
};

type HandleSignParamsType = {
setSuccess: () => void;
setWorking: () => void;
setError: () => void;
setHash: (hash: any) => void;
};

type TransactionStepsType = {
title: string;
handleSign: (params: HandleSignParamsType) => Promise<void>;
};

type ArrayTransactionStepsType = Array<TransactionStepsType> | null;

type TransactionType = {
data: any;
from: string | undefined;
to: string | undefined;
description?: string;
type?: string;
gasLimit?: number;
};

function ModalFlowBase({
loading,
screens,
transactions,
onComplete,
onCompleteActions,
frontLoad = true,
transactionTitle = "Create transaction",
}: ModalFlowBaseType) {
// const { addActivity } = useActivity();
const [{ data: signer }] = useSigner();

const transactionSteps: ArrayTransactionStepsType = useMemo(
() =>
transactions
? transactions.map((transaction: TransactionType, index: number) => {
const title = transaction.description
? transaction.description
: transactions.length === 1
? "Sign transaction"
: `${INDEX_NUMBER[index]} transaction`;

return {
// TODO: Add titles from description
title,
handleSign: async ({
setSuccess,
setWorking,
setError,
setHash,
}: HandleSignParamsType) => {
try {
const trx = {
from: transaction.from,
to: transaction.to,
data: transaction.data,
gasLimit: transaction.gasLimit,
};

// TODO: use useTransaction hook
const tx = await signer!.sendTransaction(trx);

// await addActivity(
// tx,
// transaction.type,
// transaction.description
// );
setHash(tx.hash);

setWorking();

// We need to wait for pre-transactions to mine before asking for the next signature
// TODO: Provide a better user experience than waiting on all transactions
await tx.wait();

setSuccess();
} catch (err) {
console.error(err);
setError();
}
},
};
})
: null,
[transactions, signer] // addActivity
);

const extendedScreens = useMemo(() => {
const allScreens = [];

// Add loading screen as first item if enabled
if (frontLoad) {
allScreens.push({
content: <LoadingScreen loading={loading} />,
});
}

// Spread in our flow screens
if (screens) {
allScreens.push(...screens);
}

// Apply transaction singing at the end
if (transactionSteps) {
allScreens.push({
title: transactionTitle,
width: modalWidthFromCount(transactions.length),
content: (
<Stepper
steps={transactionSteps}
onComplete={onComplete}
onCompleteActions={onCompleteActions}
/>
),
});
}

return allScreens;
}, [
frontLoad,
loading,
screens,
transactions,
transactionSteps,
transactionTitle,
onComplete,
onCompleteActions,
]);

return <MultiModalScreens screens={extendedScreens} />;
}

function LoadingScreen({ loading }: { loading: boolean }) {
const { next } = useMultiModal();

useEffect(() => {
let timeout: number;

if (!loading) {
// Provide a minimum appearance duration to avoid visual confusion on very fast requests
timeout = window.setTimeout(() => {
next();
}, 100);
}

return () => {
clearTimeout(timeout);
};
}, [loading, next]);

return <LoadingRing />;
}

function modalWidthFromCount(count: number) {
if (count >= 3) {
return 865;
}

if (count === 2) {
return 700;
}

// Modal will fallback to the default
return null;
}

export default ModalFlowBase;
Loading