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: use faucet info from chain config #341

Merged
merged 9 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Improvements

- [#341](https://github.com/alleslabs/celatone-frontend/pull/341) Apply faucet info from chain config
- [#234](https://github.com/alleslabs/celatone-frontend/pull/234) Fix faucet wording
- [#216](https://github.com/alleslabs/celatone-frontend/pull/216) Change icon to Alles Labs icon set
- [#227](https://github.com/alleslabs/celatone-frontend/pull/227) Refactor directory structure and components e.g. various tables
Expand Down
2 changes: 2 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export const CHAIN_CONFIGS: ChainConfigs = {
faucet: {
enabled: true,
url: "https://faucet.alleslabs.dev",
denom: "osmo",
amount: 10,
},
wasm: {
enabled: true,
Expand Down
2 changes: 2 additions & 0 deletions src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ type FaucetConfig =
| {
enabled: true;
url: string;
denom: string;
amount: number;
}
| { enabled: false };

Expand Down
44 changes: 14 additions & 30 deletions src/lib/app-provider/contexts/app.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useWallet } from "@cosmos-kit/react";
import { GraphQLClient } from "graphql-request";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import type { ReactNode } from "react";
import {
useCallback,
Expand All @@ -13,11 +12,10 @@ import {
} from "react";

import { useAmplitude } from "../hooks/useAmplitude";
import { useInternalNavigate } from "../hooks/useInternalNavigate";
import { useNetworkChange } from "../hooks/useNetworkChange";
import { CHAIN_CONFIGS, DEFAULT_CHAIN_CONFIG, PROJECT_CONSTANTS } from "config";
import type { ChainConfig, ProjectConstants } from "config/types";
import { DEFAULT_SUPPORTED_CHAIN_ID, SUPPORTED_CHAIN_IDS } from "env";
import { SUPPORTED_CHAIN_IDS } from "env";
import { LoadingOverlay } from "lib/components/LoadingOverlay";
import { DEFAULT_ADDRESS } from "lib/data";
import {
Expand Down Expand Up @@ -50,53 +48,38 @@ const AppContext = createContext<AppContextInterface>({
});

export const AppProvider = observer(({ children }: AppProviderProps) => {
const router = useRouter();
const navigate = useInternalNavigate();
const { currentChainName, setCurrentChain } = useWallet();

const { setCodeUserKey, isCodeUserKeyExist } = useCodeStore();
const { setContractUserKey, isContractUserKeyExist } = useContractStore();
const { setProjectUserKey, isProjectUserKeyExist } = usePublicProjectStore();

const [currentChainId, setCurrentChainId] = useState(
DEFAULT_SUPPORTED_CHAIN_ID
);
const [currentChainId, setCurrentChainId] = useState("");

// Remark: this function is only used in useSelectChain. Do not use in other places.
const handleOnChainIdChange = useCallback(
(newChainId: string) => {
const config = CHAIN_CONFIGS[newChainId];
setCurrentChainId(newChainId);
setCurrentChain(config?.registryChainName);

navigate({
pathname: router.pathname.replace("/[network]", ""),
query: {
...router.query,
network: newChainId,
},
});
},
[navigate, router, setCurrentChain]
[setCurrentChain, setCurrentChainId]
);

const chainConfig = CHAIN_CONFIGS[currentChainId];
const states = useMemo<AppContextInterface>(() => {
const chainConfig = currentChainId
? CHAIN_CONFIGS[currentChainId]
: DEFAULT_CHAIN_CONFIG;

const indexerGraphClient = useMemo(
() => new GraphQLClient(chainConfig.indexer),
[chainConfig.indexer]
);

const states = useMemo<AppContextInterface>(
() => ({
return {
availableChainIds: SUPPORTED_CHAIN_IDS,
currentChainId,
chainConfig,
indexerGraphClient,
indexerGraphClient: new GraphQLClient(chainConfig.indexer),
constants: PROJECT_CONSTANTS,
handleOnChainIdChange,
}),
[chainConfig, currentChainId, handleOnChainIdChange, indexerGraphClient]
);
};
}, [currentChainId, handleOnChainIdChange]);

useEffect(() => {
if (currentChainName) {
Expand All @@ -114,7 +97,8 @@ export const AppProvider = observer(({ children }: AppProviderProps) => {
if (
!isCodeUserKeyExist() ||
!isContractUserKeyExist() ||
!isProjectUserKeyExist()
!isProjectUserKeyExist() ||
!currentChainId
)
return <LoadingOverlay />;

Expand Down
1 change: 1 addition & 0 deletions src/lib/app-provider/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export * from "./useTokensInfo";
export * from "./useCurrentNetwork";
export * from "./useBaseApiRoute";
export * from "./useRPCEndpoint";
export * from "./useFaucetConfig";
export * from "./useWasmConfig";
11 changes: 11 additions & 0 deletions src/lib/app-provider/hooks/useFaucetConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useCelatoneApp } from "../contexts";

export const useFaucetConfig = () => {
const {
chainConfig: {
features: { faucet },
},
} = useCelatoneApp();

return faucet;
};
21 changes: 19 additions & 2 deletions src/lib/app-provider/hooks/useNetworkChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,23 @@ export const useNetworkChange = (
const networkRef = useRef<string>();

useEffect(() => {
let networkRoute = router.asPath.split("/")[1];

// TODO: refactor later
if (router.isReady) {
let networkRoute = getFirstQueryParam(
networkRoute = getFirstQueryParam(
router.query.network,
DEFAULT_SUPPORTED_CHAIN_ID
);
// Redirect to default chain if the chain is not supported by the app
if (!SUPPORTED_CHAIN_IDS.includes(networkRoute))
networkRoute = DEFAULT_SUPPORTED_CHAIN_ID;

if (networkRoute !== networkRef.current) {
networkRef.current = networkRoute;
handleOnChainIdChange(networkRoute);
}
} else if (router.pathname === "/404") {
// Redirect to default chain if the chain is not supported by the app
if (!SUPPORTED_CHAIN_IDS.includes(networkRoute))
networkRoute = DEFAULT_SUPPORTED_CHAIN_ID;
Expand All @@ -26,5 +37,11 @@ export const useNetworkChange = (
handleOnChainIdChange(networkRoute);
}
}
}, [handleOnChainIdChange, router.isReady, router.query.network]);
}, [
handleOnChainIdChange,
router.asPath,
router.isReady,
router.pathname,
router.query.network,
]);
};
14 changes: 13 additions & 1 deletion src/lib/app-provider/hooks/useSelectChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,28 @@ import { useCallback } from "react";

import { useCelatoneApp } from "../contexts/app";

import { useInternalNavigate } from "./useInternalNavigate";

export const useSelectChain = () => {
const router = useRouter();
const navigator = useInternalNavigate();
const { handleOnChainIdChange } = useCelatoneApp();

return useCallback(
(chainId: string) => {
if (router.query.network === chainId) return;

// Remark: This is workaround solution to set new chainId and replace the pathname
handleOnChainIdChange(chainId);

navigator({
pathname: router.pathname.replace("/[network]", ""),
query: {
...router.query,
network: chainId,
},
});
},
[handleOnChainIdChange, router.query.network]
[handleOnChainIdChange, navigator, router.pathname, router.query]
);
};
6 changes: 0 additions & 6 deletions src/lib/app-provider/hooks/useWasmConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,5 @@ export const useWasmConfig = () => {
},
} = useCelatoneApp();

if (!wasm.enabled) {
throw new Error(
"Cannot access Wasm configs when Wasm feature is disabled."
);
}

return wasm;
};
18 changes: 15 additions & 3 deletions src/lib/app-provider/tx/clearAdmin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ export const useClearAdminTx = (contractAddress: ContractAddr) => {
const fabricateFee = useFabricateFee();
const wasm = useWasmConfig();

const clearAdminFee = fabricateFee(wasm.clearAdminGas);

return useCallback(
async ({ onTxSucceed }: ClearAdminStreamParams) => {
const client = await getCosmWasmClient();
if (!address || !client)
throw new Error("Please check your wallet connection.");

if (!wasm.enabled)
throw new Error(
"Wasm config isn't loaded or Wasm feature is disabled."
);

const clearAdminFee = fabricateFee(wasm.clearAdminGas);

return clearAdminTx({
address: address as HumanAddr,
contractAddress,
Expand All @@ -42,6 +47,13 @@ export const useClearAdminTx = (contractAddress: ContractAddr) => {
},
});
},
[address, clearAdminFee, queryClient, contractAddress, getCosmWasmClient]
[
getCosmWasmClient,
address,
wasm,
fabricateFee,
contractAddress,
queryClient,
]
);
};
12 changes: 9 additions & 3 deletions src/lib/components/button/FaucetButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import { Button, Text } from "@chakra-ui/react";
import type { MouseEventHandler } from "react";

import { CustomIcon } from "../icon";
import { useCurrentNetwork, useInternalNavigate } from "lib/app-provider";
import { useCelatoneApp, useInternalNavigate } from "lib/app-provider";

export const FaucetBtn = () => {
const navigate = useInternalNavigate();
const { isTestnet } = useCurrentNetwork();
const {
chainConfig: {
features: {
faucet: { enabled },
},
},
} = useCelatoneApp();

const onClick: MouseEventHandler = async (e) => {
e.preventDefault();
Expand All @@ -15,7 +21,7 @@ export const FaucetBtn = () => {
});
};

return isTestnet ? (
return enabled ? (
<Button
variant="outline-gray"
leftIcon={<CustomIcon name="faucet" color="text.dark" />}
Expand Down
48 changes: 34 additions & 14 deletions src/lib/pages/faucet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import { useWallet } from "@cosmos-kit/react";
import type { AxiosError, AxiosResponse } from "axios";
import axios from "axios";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";

import {
useCurrentNetwork,
useCelatoneApp,
useFaucetConfig,
useInternalNavigate,
useValidateAddress,
} from "lib/app-provider";
Expand All @@ -25,6 +26,7 @@ import type { IconKeys } from "lib/components/icon";
import WasmPageContainer from "lib/components/WasmPageContainer";
import { useOpenTxTab } from "lib/hooks";
import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import { capitalize } from "lib/utils";

type ResultStatus = "success" | "error" | "warning";

Expand All @@ -49,18 +51,36 @@ const Faucet = () => {
const [result, setResult] = useState<Result>({});

const { validateUserAddress } = useValidateAddress();
const { isTestnet } = useCurrentNetwork();
const navigate = useInternalNavigate();
const toast = useToast();
const router = useRouter();
const openTxTab = useOpenTxTab("tx-page");

const faucetUrl = process.env.NEXT_PUBLIC_FAUCET_URL;
const {
chainConfig: { chain },
} = useCelatoneApp();
const faucet = useFaucetConfig();

const { faucetUrl, faucetDenom, faucetAmount } = useMemo(() => {
if (!faucet.enabled)
// Remark: this shouldn't be used as the faucet is disabled
return {
faucetUrl: "",
faucetDenom: "",
faucetAmount: "",
};

return {
faucetUrl: faucet.url,
faucetDenom: faucet.denom.toUpperCase(),
faucetAmount: faucet.amount,
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [faucet.enabled]);

useEffect(() => {
if (!isTestnet) navigate({ pathname: "/" });
if (!faucet.enabled) navigate({ pathname: "/", replace: true });
else if (router.isReady) AmpTrack(AmpEvent.TO_FAUCET);
}, [isTestnet, navigate, router]);
}, [faucet, navigate, router]);

useEffect(() => {
if (address) {
Expand Down Expand Up @@ -89,7 +109,7 @@ const Faucet = () => {
})
.then(({ data: { txHash } }) => {
toast({
title: "10 Testnet OSMO sent from the faucet",
title: `${faucetAmount} Testnet ${faucetDenom} sent from the faucet`,
status: "success",
duration: 5000,
isClosable: false,
Expand All @@ -109,8 +129,7 @@ const Faucet = () => {
setIsLoading(false);
setResult({
status: "success",
message:
"Sent 10 testnet OSMO from the faucet. You will need to wait for another hour to request again.",
message: `Sent ${faucetAmount} testnet ${faucetDenom} from the faucet. You will need to wait for another hour to request again.`,
txHash,
});
})
Expand Down Expand Up @@ -146,11 +165,12 @@ const Faucet = () => {
<WasmPageContainer>
<BackButton alignSelf="flex-start" />
<Heading as="h5" variant="h5">
Osmosis Testnet Faucet
{capitalize(chain)} Testnet Faucet
</Heading>
<Text variant="body2" color="text.dark" pt={4} textAlign="center" mb={8}>
The faucet provides 10 testnet OSMO per request. Requests are limited to
once per hour for each receiving address and IP address.
The faucet provides {faucetAmount} testnet {faucetDenom} per request.
Requests are limited to once per hour for each receiving address and IP
address.
</Text>
<TextInput
variant="floating"
Expand Down Expand Up @@ -182,7 +202,7 @@ const Faucet = () => {
isLoading={isLoading}
disabled={disabled}
>
Request 10 testnet OSMO
Request {faucetAmount} testnet {faucetDenom}
evilpeach marked this conversation as resolved.
Show resolved Hide resolved
</Button>
{result.status && (
<Alert mt={8} variant={result.status}>
Expand Down
3 changes: 3 additions & 0 deletions src/lib/utils/formatter/text.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export const capitalize = (text: string) =>
text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();

export const removeSpecialChars = (text: string) =>
text.replace(/[^a-zA-Z0-9]/g, "");