Skip to content

Commit

Permalink
Merge pull request #341 from alleslabs/feat/faucet-config
Browse files Browse the repository at this point in the history
feat: use faucet info from chain config
  • Loading branch information
poomthiti committed May 25, 2023
2 parents 1ad3bc0 + fc16281 commit 2b6b345
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 63 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,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;
};
17 changes: 11 additions & 6 deletions src/lib/app-provider/hooks/useNetworkChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ export const useNetworkChange = (
const networkRef = useRef<string>();

useEffect(() => {
if (router.isReady) {
let networkRoute = getFirstQueryParam(
router.query.network,
DEFAULT_SUPPORTED_CHAIN_ID
);
let networkRoute = router.query.network
? getFirstQueryParam(router.query.network, DEFAULT_SUPPORTED_CHAIN_ID)
: router.asPath.split("/")[1];

if (router.isReady || 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 +25,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}
</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, "");

0 comments on commit 2b6b345

Please sign in to comment.