Skip to content

Commit

Permalink
Merge pull request #1208 from alleslabs/feat/interaction-section
Browse files Browse the repository at this point in the history
feat: interaction section
  • Loading branch information
Poafs1 authored Jan 29, 2025
2 parents b61fd52 + 6257a7a commit 944d128
Show file tree
Hide file tree
Showing 49 changed files with 1,371 additions and 233 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#1209](https://github.com/alleslabs/celatone-frontend/pull/1209) Implement evm contract details interaction
- [#1208](https://github.com/alleslabs/celatone-frontend/pull/1208) Implement evm interaction section
- [#1207](https://github.com/alleslabs/celatone-frontend/pull/1207) Add EVM contract details compiler settings
- [#1206](https://github.com/alleslabs/celatone-frontend/pull/1206) Add EVM contract details abi
- [#1204](https://github.com/alleslabs/celatone-frontend/pull/1204) Add EVM contract details deployed bytecode
Expand Down
3 changes: 3 additions & 0 deletions src/lib/amplitude/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ export enum AmpEvent {
ACTION_MOVE_EXECUTE = "Action Move Execute",
ACTION_MOVE_PUBLISH = "Action Move Publish",
ACTION_EXECUTE_SCRIPT = "Action Execute Script",
ACTION_EVM_WRITE = "Action Evm Write",
ACTION_EVM_READ = "Action Evm Read",
ACTION_EVM_READ_AGAIN = "Action Evm Read Again",
// INTERACTS
USE_SELECT_NETWORK = "Use Select Network",
USE_CLICK_WALLET = "Use Click Wallet",
Expand Down
10 changes: 9 additions & 1 deletion src/lib/app-fns/tx/evm/requestEvm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import type { HexAddr, TxResultRendering } from "lib/types";
import { TxStreamPhase } from "lib/types";
import { catchTxError, postEvmTx } from "../common";
import { sendingEvmTx } from "../common/sendingEvm";
import { toBeHex } from "ethers";

interface RequestEvmTxParams {
to: HexAddr;
data: string;
value: string;
estimatedFee: SimulatedFeeEvm;
signAndBroadcastEvm: SignAndBroadcastEvm;
onTxSucceed?: () => void;
Expand All @@ -23,6 +25,7 @@ interface RequestEvmTxParams {
export const requestEvmTx = ({
to,
data,
value,
estimatedFee,
signAndBroadcastEvm,
onTxSucceed,
Expand All @@ -31,7 +34,12 @@ export const requestEvmTx = ({
return pipe(
sendingEvmTx(estimatedFee),
postEvmTx<TxReceiptJsonRpc>({
postFn: () => signAndBroadcastEvm({ to, data }),
postFn: () =>
signAndBroadcastEvm({
to,
data,
value: value ? toBeHex(value) : null,
}),
}),
(txResult) => {
onTxSucceed?.();
Expand Down
1 change: 1 addition & 0 deletions src/lib/app-provider/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export enum CELATONE_QUERY_KEYS {
EVM_TX_HASHES_BY_COSMOS_TX_HASHES = "CELATONE_QUERY_EVM_TX_HASHES_BY_COSMOS_TX_HASHES",
COSMOS_TX_HASH_BY_EVM_TX_HASH = "CELATONE_QUERY_COSMOS_TX_HASH_BY_EVM_TX_HASH",
EVM_ETH_CALL = "CELATONE_QUERY_EVM_ETH_CALL",
EVM_PROXY_TARGET = "CELATONE_QUERY_EVM_PROXY_TARGET",
// RESOURCE
RESOURCES_BY_ADDRESS = "CELATONE_QUERY_RESOURCES_BY_ADDRESS",
// NFTS
Expand Down
2 changes: 1 addition & 1 deletion src/lib/app-provider/hooks/useAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const useGetAddressTypeByLength = () => {
return useCallback(
(address: Option<string>): AddressReturnType =>
address
? addressLengthMap[address.length] ?? "invalid_address"
? (addressLengthMap[address.length] ?? "invalid_address")
: "invalid_address",
[addressLengthMap]
);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/app-provider/hooks/useExampleAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const useExampleAddresses = () => {

// reverse the bytes so the initial characters are different from the user address
const evmContract = "0x" + toHex(Uint8Array.from(bytes20).reverse());
const wasmContract = toBech32(
const contract = toBech32(
bech32Prefix,
Uint8Array.from(bytes32.reverse())
) as BechAddr32;
Expand All @@ -25,7 +25,7 @@ export const useExampleAddresses = () => {

return {
user,
wasmContract,
contract,
evmContract,
validator,
};
Expand Down
19 changes: 6 additions & 13 deletions src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { useCallback } from "react";

import { TransactionRequest } from "ethers";
import { requestJsonRpc } from "lib/services/evm/jsonRpc";
import { TxReceiptJsonRpc, zTxReceiptJsonRpc } from "lib/services/types";
import {
convertCosmosChainIdToEvmChainId,
parseWithError,
sleep,
} from "lib/utils";
import { getEthGetTransactionReceipt } from "lib/services/evm/json-rpc";
import { TxReceiptJsonRpc } from "lib/services/types";
import { convertCosmosChainIdToEvmChainId, sleep } from "lib/utils";
import { useCelatoneApp } from "../contexts";
import { useCurrentChain } from "./useCurrentChain";

Expand All @@ -29,13 +25,10 @@ const getEvmTxResponse = async (jsonRpcEndpoint: string, txHash: string) => {
);
}
await sleep(POLL_INTERVAL_MS);
const result = await requestJsonRpc(
const result = await getEthGetTransactionReceipt(
jsonRpcEndpoint,
"eth_getTransactionReceipt",
[txHash]
)
.then((result) => parseWithError(zTxReceiptJsonRpc, result))
.catch(() => undefined);
txHash
).catch(() => undefined);
return result ? result : pollForEvmTx(_txHash);
};

Expand Down
3 changes: 3 additions & 0 deletions src/lib/app-provider/tx/evm/requestEvm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { HexAddr20 } from "lib/types";
export interface RequestEvmStreamParams {
to: HexAddr20;
data: string;
value: string;
estimatedFee?: SimulatedFeeEvm;
onTxSucceed?: () => void;
onTxFailed?: () => void;
Expand All @@ -21,6 +22,7 @@ export const useRequestEvmTx = () => {
async ({
to,
data,
value,
estimatedFee,
onTxSucceed,
onTxFailed,
Expand All @@ -30,6 +32,7 @@ export const useRequestEvmTx = () => {
return requestEvmTx({
to,
data,
value,
estimatedFee,
signAndBroadcastEvm,
onTxSucceed: () => {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/ContractInputSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const ContractInputSection = ({
}: ContractInputSectionProps) => {
const [isChangeContract, setIsChangeContract] = useState(false);
const { address } = useCurrentChain();
const { wasmContract: contractExample } = useExampleAddresses();
const { contract: contractExample } = useExampleAddresses();
const { control, setValue, watch } = useForm({
defaultValues: {
contractAddress: "",
Expand Down
7 changes: 4 additions & 3 deletions src/lib/components/EstimatedFeeEvmRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import Big from "big.js";

import { useAssetInfos } from "lib/services/assetService";
import { useEvmParams } from "lib/services/evm";
import { Option } from "lib/types";
import { coinToTokenWithValue, formatTokenWithValue } from "lib/utils";

export const EstimatedFeeEvmRender = ({
gasPrice,
gasUsed,
loading,
}: {
gasPrice: Big;
gasUsed: Big;
gasPrice: Option<Big>;
gasUsed: Option<Big>;
loading: boolean;
}) => {
const { data: assetInfos, isLoading: isAssetInfoLoading } = useAssetInfos({
Expand All @@ -29,7 +30,7 @@ export const EstimatedFeeEvmRender = ({
);

const feeDenom = evmParams?.params.feeDenom;
if (!feeDenom) return <>--</>;
if (!gasPrice || !gasUsed || !feeDenom) return <>--</>;

const feeAmount = gasPrice.mul(gasUsed);
const feeToken = coinToTokenWithValue(
Expand Down
26 changes: 16 additions & 10 deletions src/lib/components/evm-abi/EvmAbiForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ import { cloneDeep } from "lodash";

interface EvmAbiFormProps {
types: ReadonlyArray<JsonFragmentType>;
isPayable: boolean;
isPayable?: boolean;
initialData?: JsonDataType[];
propsOnChange?: (data: JsonDataType[]) => void;
propsOnChangeInputs?: (data: JsonDataType[]) => void;
propsOnChangeValue?: (value: string) => void;
isDisabled?: boolean;
}

export const EvmAbiForm = ({
types,
isPayable,
isPayable = false,
initialData,
propsOnChange,
propsOnChangeInputs,
propsOnChangeValue,
isDisabled,
}: EvmAbiFormProps) => {
const defaultValues = useMemo(
Expand All @@ -29,22 +31,26 @@ export const EvmAbiForm = ({

const { control, reset, watch } = useForm<{
inputs: JsonDataType[];
payableAmount: string;
value: string;
}>({
defaultValues: { inputs: defaultValues, payableAmount: "" },
defaultValues: { inputs: defaultValues, value: "" },
mode: "all",
});
const { inputs } = watch();
const { inputs, value } = watch();

useEffect(() => {
reset({ inputs: defaultValues });
reset({ inputs: defaultValues, value: "" });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(defaultValues), reset]);

useEffect(() => {
propsOnChange?.(cloneDeep(inputs));
propsOnChangeInputs?.(cloneDeep(inputs));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(inputs), propsOnChange]);
}, [JSON.stringify(inputs), propsOnChangeInputs]);

useEffect(() => {
propsOnChangeValue?.(value);
}, [value, propsOnChangeValue]);

return (
<FormFields
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/evm-abi/fields/TupleField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const TupleField = <T extends FieldValues>({
key={`${subfieldType}-${index}`}
label={subfieldLabel}
type={subfieldType}
isRequired
isRequired={!isDisabled}
>
<FieldTemplate
name={`${name}.${index}` as FieldPath<T>}
Expand Down
32 changes: 24 additions & 8 deletions src/lib/components/evm-abi/fields/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TypeLabel } from "./TypeLabel";
import { useEvmParams } from "lib/services/evm";
import { useAssetInfos } from "lib/services/assetService";
import { getTokenLabel } from "lib/utils";
import { Text } from "@chakra-ui/react";

interface FormFieldsProps<T extends FieldValues> {
control: Control<T>;
Expand All @@ -32,21 +33,36 @@ export const FormFields = <T extends FieldValues>({

return (
<>
<TupleField
control={control}
name={"inputs" as Path<T>}
components={components}
isDisabled={isDisabled}
withoutBorder
/>
{components.length > 0 ? (
<TupleField
control={control}
name={"inputs" as Path<T>}
components={components}
isDisabled={isDisabled}
withoutBorder
/>
) : (
<Text
variant="body2"
textColor="text.disabled"
fontWeight={500}
bgColor="gray.800"
w="full"
py={4}
borderRadius="4px"
textAlign="center"
>
Empty {isDisabled ? "Output" : "Input"}
</Text>
)}
{isPayable && (
<TypeLabel
label={`Send native${feeLabel ? ` ${feeLabel}` : ""}`}
type="uint256"
>
<BaseField
control={control}
name={"payableAmount" as Path<T>}
name={"value" as Path<T>}
type="uint256"
/>
</TypeLabel>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/components/filter/FilterInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface FilterInputProps {
isDropdown: boolean;
chipContainerComponent: JSX.Element;
inputRef: RefObject<HTMLInputElement>;
ref: ForwardedRef<HTMLInputElement>;
mainRef: ForwardedRef<HTMLInputElement>;
placeholder?: string;
label?: string;
setIsDropdown: Dispatch<SetStateAction<boolean>>;
Expand All @@ -23,7 +23,7 @@ export const FilterInput = ({
isDropdown,
label,
inputRef,
ref,
mainRef,
setIsDropdown,
setKeyword,
chipContainerComponent,
Expand All @@ -47,7 +47,7 @@ export const FilterInput = ({
size="lg"
minW="150px"
placeholder={result.length > 0 ? "" : placeholder}
ref={mergeRefs([inputRef, ref])}
ref={mergeRefs([inputRef, mainRef])}
maxLength={36}
style={{ border: 0, maxHeight: "54px" }}
onFocus={() => setIsDropdown(true)}
Expand Down
Loading

0 comments on commit 944d128

Please sign in to comment.