view parsed calldata as modal window

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2026-02-13 13:17:16 +03:00
parent 30a78327cc
commit 7457926952
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
5 changed files with 101 additions and 42 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "ghost-dao-interface", "name": "ghost-dao-interface",
"private": true, "private": true,
"version": "0.5.11", "version": "0.5.12",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -86,6 +86,8 @@ const BondInputArea = ({
: bond.capacity.inBaseToken : bond.capacity.inBaseToken
); );
console.log(bond.quoteToken.icons)
return ( return (
<Box minHeight="calc(100vh - 210px)" display="flex" flexDirection="column" justifyContent="center"> <Box minHeight="calc(100vh - 210px)" display="flex" flexDirection="column" justifyContent="center">
<Box display="flex" flexDirection="row" width="100%" justifyContent="center" mt="10px"> <Box display="flex" flexDirection="row" width="100%" justifyContent="center" mt="10px">

View File

@ -2,9 +2,12 @@ import { useRef, useMemo, useState, useEffect } from "react";
import { encodeFunctionData } from 'viem'; import { encodeFunctionData } from 'viem';
import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material"; import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material";
import Modal from "../../../../components/Modal/Modal";
import Select from "../../../../components/Select/Select"; import Select from "../../../../components/Select/Select";
import { PrimaryButton, TertiaryButton } from "../../../../components/Button"; import { PrimaryButton, TertiaryButton } from "../../../../components/Button";
import { shorten } from "../../../../helpers"; import { shorten } from "../../../../helpers";
import { useTokenSymbol } from "../../../../hooks/tokens";
import { BooleanTrigger, ArgumentInput, ParsedCell } from "./index"; import { BooleanTrigger, ArgumentInput, ParsedCell } from "./index";
import { import {
@ -29,9 +32,26 @@ export const prepareCreateBondCalldata = (chainId, markets, terms, quoteToken, i
export const prepareCreateBondDescription = "Create Bond function creates a new bond market by processing pricing, capacity, and term inputs. It initializes and stores the new bond market's complete configuration in the protocol."; export const prepareCreateBondDescription = "Create Bond function creates a new bond market by processing pricing, capacity, and term inputs. It initializes and stores the new bond market's complete configuration in the protocol.";
export const CreateBondParsed = (props) => { export const CreateBondParsed = (props) => {
const [isOpened, setIsOpened] = useState(false);
const { symbol: ftsoSymbol } = useTokenSymbol(props.chainId, "FTSO");
return ( return (
<> <>
{props.isTable && <CreateBondParsedCell {...props} />} <Modal
headerContent={
<Box display="flex" justifyContent="center" alignItems="center" gap="15px">
<Typography variant="h4">View Create Bond</Typography>
</Box>
}
open={isOpened}
onClose={() => setIsOpened(false)}
maxWidth="460px"
minHeight="200px"
>
<Box minHeight="220px" display="flex" alignItems="start" justifyContent="space-between" flexDirection="column">
<CreateBondSteps args={props.args} ftsoSymbol={ftsoSymbol} nativeCurrency={props.nativeCoin} {...props} />
</Box>
</Modal>
{props.isTable && <CreateBondParsedCell isOpened={isOpened} setIsOpened={setIsOpened} {...props}/>}
</> </>
) )
} }
@ -40,23 +60,25 @@ const CreateBondParsedCell = (props) => {
return <ParsedCell {...props} /> return <ParsedCell {...props} />
} }
export const CreateBondSteps = ({ nativeCurrency, ftsoSymbol, chainId, toInitialStep, addCalldata }) => { export const CreateBondSteps = ({ nativeCurrency, ftsoSymbol, chainId, toInitialStep, addCalldata, args }) => {
const createMode = args === undefined;
const [step, setStep] = useState(1); const [step, setStep] = useState(1);
const [nextDisabled, setNextDisabled] = useState(false); const [nextDisabled, setNextDisabled] = useState(false);
const [capacity, setCapacity] = useState(); const [capacity, setCapacity] = useState(args?.at(0)?.at(0));
const [initialPrice, setInitialPrice] = useState(); const [initialPrice, setInitialPrice] = useState(args?.at(0)?.at(1));
const [debtBuffer, setDebtBuffer] = useState(); const [debtBuffer, setDebtBuffer] = useState(args?.at(0)?.at(2));
const [depositInterval, setDepositInterval] = useState(); const [depositInterval, setDepositInterval] = useState(args?.at(3)?.at(0));
const [tuneInterval, setTuneInterval] = useState(); const [tuneInterval, setTuneInterval] = useState(args?.at(3)?.at(1));
const [tokenAddress, setTokenAddress] = useState(); const [tokenAddress, setTokenAddress] = useState(args?.at(2));
const [capacityInQuote, setCapacityInQuote] = useState(true); const [capacityInQuote, setCapacityInQuote] = useState(args?.at(4)?.at(0) ?? true);
const [fixedTerm, setFixedTerm] = useState(false); const [fixedTerm, setFixedTerm] = useState(args?.at(4)?.at(1) ?? false);
const [vestingLength, setVestingLength] = useState(); const [vestingLength, setVestingLength] = useState(args?.at(1)?.at(0));
const [conclusionTimestamp, setConclusionTimestamp] = useState(); const [conclusionTimestamp, setConclusionTimestamp] = useState(args?.at(1)?.at(1));
const handleProceed = () => { const handleProceed = () => {
const markets = [capacity, initialPrice, debtBuffer]; const markets = [capacity, initialPrice, debtBuffer];
@ -67,6 +89,8 @@ export const CreateBondSteps = ({ nativeCurrency, ftsoSymbol, chainId, toInitial
addCalldata(prepareCreateBondCalldata(chainId, markets, terms, tokenAddress, intervals, booleans)) addCalldata(prepareCreateBondCalldata(chainId, markets, terms, tokenAddress, intervals, booleans))
} }
const empty = () => {};
const incrementStep = () => { const incrementStep = () => {
setStep(prev => prev + 1); setStep(prev => prev + 1);
} }
@ -99,45 +123,47 @@ export const CreateBondSteps = ({ nativeCurrency, ftsoSymbol, chainId, toInitial
return ( return (
<Box height="100%" width="100%" display="flex" flexDirection="column" justifyContent="space-between"> <Box height="100%" width="100%" display="flex" flexDirection="column" justifyContent="space-between">
{step === 1 && <TokenAndBooleansArguments {step === 1 && <TokenAndBooleansArguments
tokenAddress={tokenAddress}
createMode={createMode}
possibleTokens={possibleTokens} possibleTokens={possibleTokens}
setTokenAddress={setTokenAddress} setTokenAddress={createMode ? setTokenAddress : empty}
nativeCurrency={nativeCurrency} nativeCurrency={nativeCurrency}
ftsoSymbol={ftsoSymbol} ftsoSymbol={ftsoSymbol}
capacityInQuote={capacityInQuote} capacityInQuote={capacityInQuote}
setCapacityInQuote={setCapacityInQuote} setCapacityInQuote={createMode ? setCapacityInQuote : empty}
fixedTerm={fixedTerm} fixedTerm={fixedTerm}
setFixedTerm={setFixedTerm} setFixedTerm={createMode ? setFixedTerm : empty}
/>} />}
{step === 2 && <MarketArguments {step === 2 && <MarketArguments
capacityInQuote={capacityInQuote} capacityInQuote={capacityInQuote}
nativeCurrency={nativeCurrency} nativeCurrency={nativeCurrency}
ftsoSymbol={ftsoSymbol} ftsoSymbol={ftsoSymbol}
capacity={capacity} capacity={capacity}
setCapacity={setCapacity} setCapacity={createMode ? setCapacity : empty}
initialPrice={initialPrice} initialPrice={initialPrice}
setInitialPrice={setInitialPrice} setInitialPrice={createMode ? setInitialPrice : empty}
debtBuffer={debtBuffer} debtBuffer={debtBuffer}
setDebtBuffer={setDebtBuffer} setDebtBuffer={createMode ? setDebtBuffer : empty}
/>} />}
{step === 3 && <IntervalsArguments {step === 3 && <IntervalsArguments
depositInterval={depositInterval} depositInterval={depositInterval}
setDepositInterval={setDepositInterval} setDepositInterval={createMode ? setDepositInterval : empty}
tuneInterval={tuneInterval} tuneInterval={tuneInterval}
setTuneInterval={setTuneInterval} setTuneInterval={createMode ? setTuneInterval : empty}
/>} />}
{step === 4 && <TermsAgruments {step === 4 && <TermsAgruments
fixedTerm={fixedTerm} fixedTerm={fixedTerm}
vestingLength={vestingLength} vestingLength={vestingLength}
setVestingLength={setVestingLength} setVestingLength={createMode ? setVestingLength : empty}
conclusionTimestamp={conclusionTimestamp} conclusionTimestamp={conclusionTimestamp}
setConclusionTimestamp={setConclusionTimestamp} setConclusionTimestamp={createMode ? setConclusionTimestamp : empty}
/>} />}
<Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px"> <Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px">
<Box display="flex" gap="10px"> <Box display="flex" gap="10px">
<TertiaryButton onClick={() => decrementStep()} fullWidth>Back</TertiaryButton> <TertiaryButton onClick={() => decrementStep()} fullWidth>Back</TertiaryButton>
<TertiaryButton disabled={isNextDisabled} onClick={() => incrementStep()} fullWidth>Next</TertiaryButton> <TertiaryButton disabled={isNextDisabled} onClick={() => incrementStep()} fullWidth>Next</TertiaryButton>
</Box> </Box>
{step === 4 && <PrimaryButton onClick={() => handleProceed()} fullWidth>Create Function</PrimaryButton>} {(step === 4 && createMode) && <PrimaryButton onClick={() => handleProceed()} fullWidth>Create Function</PrimaryButton>}
</Box> </Box>
</Box> </Box>
); );
@ -237,6 +263,8 @@ const TermsAgruments = ({
} }
const TokenAndBooleansArguments = ({ const TokenAndBooleansArguments = ({
createMode,
tokenAddress,
possibleTokens, possibleTokens,
nativeCurrency, nativeCurrency,
ftsoSymbol, ftsoSymbol,
@ -247,11 +275,13 @@ const TokenAndBooleansArguments = ({
setFixedTerm, setFixedTerm,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const [selectedOption, setSelectedOption] = useState(); const [selectedOption, setSelectedOption] = useState(tokenAddress);
const handleChange = (event) => { const handleChange = (event) => {
setSelectedOption(event.target.value); if (createMode) {
setTokenAddress(event.target.value); setSelectedOption(event.target.value);
setTokenAddress(event.target.value);
}
}; };
return ( return (

View File

@ -2,6 +2,7 @@ import { useState } from "react";
import { encodeFunctionData } from 'viem'; import { encodeFunctionData } from 'viem';
import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material"; import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material";
import Modal from "../../../../components/Modal/Modal";
import { PrimaryButton, TertiaryButton } from "../../../../components/Button"; import { PrimaryButton, TertiaryButton } from "../../../../components/Button";
import { import {
@ -26,9 +27,25 @@ export const prepareSetAdjustmentCalldata = (chainId, rateChange, targetRate, in
export const prepareSetAdjustmentDescription = "Set Adjustment function schedules a gradual change to the staking APY. It increases or decreases the staking APY by a specified rate per epoch until a target rate reached."; export const prepareSetAdjustmentDescription = "Set Adjustment function schedules a gradual change to the staking APY. It increases or decreases the staking APY by a specified rate per epoch until a target rate reached.";
export const SetAdjustmentParsed = (props) => { export const SetAdjustmentParsed = (props) => {
const [isOpened, setIsOpened] = useState(false);
return ( return (
<> <>
{props.isTable && <SetAdjustmentParsedCell {...props} />} <Modal
headerContent={
<Box display="flex" justifyContent="center" alignItems="center" gap="15px">
<Typography variant="h4">View Set Adjustment</Typography>
</Box>
}
open={isOpened}
onClose={() => setIsOpened(false)}
maxWidth="460px"
minHeight="200px"
>
<Box minHeight="220px" display="flex" alignItems="start" justifyContent="space-between" flexDirection="column">
<SetAdjustmentSteps {...props} />
</Box>
</Modal>
{props.isTable && <SetAdjustmentParsedCell isOpened={isOpened} setIsOpened={setIsOpened} {...props} />}
</> </>
) )
} }
@ -37,10 +54,12 @@ const SetAdjustmentParsedCell = (props) => {
return <ParsedCell {...props} /> return <ParsedCell {...props} />
} }
export const SetAdjustmentSteps = ({ chainId, toInitialStep, addCalldata }) => { export const SetAdjustmentSteps = ({ chainId, toInitialStep, addCalldata, args }) => {
const [rate, setRate] = useState(); const createMode = args === undefined;
const [target, setTarget] = useState();
const [increase, setIncrease] = useState(false); const [rate, setRate] = useState(args?.at(0));
const [target, setTarget] = useState(args?.at(1));
const [increase, setIncrease] = useState(args?.at(1) ?? true);
const handleProceed = () => { const handleProceed = () => {
addCalldata(prepareSetAdjustmentCalldata(chainId, rate, target, increase)); addCalldata(prepareSetAdjustmentCalldata(chainId, rate, target, increase));
@ -53,27 +72,29 @@ export const SetAdjustmentSteps = ({ chainId, toInitialStep, addCalldata }) => {
value={increase} value={increase}
leftText="Add" leftText="Add"
rightText="Sub" rightText="Sub"
setLeftValue={() => setIncrease(true)} setLeftValue={() => createMode ? setIncrease(true) : {}}
setRightValue={() => setIncrease(false)} setRightValue={() => createMode ? setIncrease(false) : {}}
label="Direction" label="Direction"
tooltip="Determines the direction of the adjustment. When Add the parameter value will gradually increase; when Sub, it will decrease toward the target rate" tooltip="Determines the direction of the adjustment. When Add the parameter value will gradually increase; when Sub, it will decrease toward the target rate"
/> />
<ArgumentInput <ArgumentInput
disabled={!createMode}
endString="%" endString="%"
label="Change Rate" label="Change Rate"
value={rate ?? ""} value={rate ?? ""}
setValue={setRate} setValue={createMode ? setRate : () => {}}
tooltip="Each epoch, the current staking reward rate changes by this amount until the target rate is reached" tooltip="Each epoch, the current staking reward rate changes by this amount until the target rate is reached"
/> />
<ArgumentInput <ArgumentInput
disabled={!createMode}
endString="%" endString="%"
label="Target Rate" label="Target Rate"
value={target ?? ""} value={target ?? ""}
setValue={setTarget} setValue={createMode ? setTarget : () => {}}
tooltip="The final desired value for the reward rate, the adjustment process will continue automatically until this specific level is reached" tooltip="The final desired value for the reward rate, the adjustment process will continue automatically until this specific level is reached"
/> />
</Box> </Box>
<Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px"> {createMode && <Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px">
<Box display="flex" gap="10px"> <Box display="flex" gap="10px">
<TertiaryButton onClick={toInitialStep} fullWidth>Back</TertiaryButton> <TertiaryButton onClick={toInitialStep} fullWidth>Back</TertiaryButton>
<TertiaryButton disabled fullWidth>Next</TertiaryButton> <TertiaryButton disabled fullWidth>Next</TertiaryButton>
@ -85,7 +106,7 @@ export const SetAdjustmentSteps = ({ chainId, toInitialStep, addCalldata }) => {
> >
Create Function Create Function
</PrimaryButton> </PrimaryButton>
</Box> </Box>}
</Box> </Box>
); );
} }

View File

@ -67,8 +67,10 @@ export const parseFunctionCalldata = (metadata, index, chainId, nativeCoin, remo
case "setAdjustment": case "setAdjustment":
return <SetAdjustmentParsed return <SetAdjustmentParsed
isTable isTable
args={args}
key={index} key={index}
label={label} label={label}
chainId={chainId}
remove={remove} remove={remove}
nativeCoin={nativeCoin} nativeCoin={nativeCoin}
value={value} value={value}
@ -78,8 +80,10 @@ export const parseFunctionCalldata = (metadata, index, chainId, nativeCoin, remo
case "create": case "create":
return <CreateBondParsed return <CreateBondParsed
isTable isTable
args={args}
key={index} key={index}
label={label} label={label}
chainId={chainId}
remove={remove} remove={remove}
nativeCoin={nativeCoin} nativeCoin={nativeCoin}
value={value} value={value}
@ -196,6 +200,7 @@ export const ArgumentInput = ({
tooltip, tooltip,
value, value,
setValue, setValue,
disabled,
inputType = "number", inputType = "number",
placeholder = "0", placeholder = "0",
maxWidth = "100%" maxWidth = "100%"
@ -222,6 +227,7 @@ export const ArgumentInput = ({
> >
<Box width="100%" display="flex" flexDirection="row" justifyContent="space-between" alignItems="center"> <Box width="100%" display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
<StyledInputBase <StyledInputBase
disabled={disabled}
placeholder={placeholder} placeholder={placeholder}
type={inputType} type={inputType}
fontSize="20px" fontSize="20px"
@ -266,12 +272,12 @@ export const ParsedCell = (props) => {
<Typography>{formatCurrency(props.value, 2, props.nativeCoin)}</Typography> <Typography>{formatCurrency(props.value, 2, props.nativeCoin)}</Typography>
</TableCell> </TableCell>
{props.remove && <TableCell> <TableCell>
<div style={{ display: 'flex', gap: '8px' }}> <div style={{ display: 'flex', gap: '8px' }}>
<TertiaryButton fullWidth onClick={() => alert("Do we need it????")}>Edit</TertiaryButton> {props.args && <TertiaryButton fullWidth onClick={() => props.setIsOpened(!props.isOpened)}>View</TertiaryButton>}
<TertiaryButton fullWidth onClick={() => props.remove()}>Delete</TertiaryButton> {props.remove && <TertiaryButton fullWidth onClick={() => props.remove()}>Delete</TertiaryButton>}
</div> </div>
</TableCell>} </TableCell>
</TableRow> </TableRow>
) )
} }