Skip to content

Commit

Permalink
chore: connect modular with leap
Browse files Browse the repository at this point in the history
  • Loading branch information
camewell071 committed Jan 22, 2024
1 parent bca14c1 commit 0674033
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/components/ConnectModal/modal.evm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const ITEMS: ModalItem[] = [
},
];

export const MESSAGE_EVM = 'Are you a Modular Blockchain Pioneer?'
export const MESSAGE_EVM = 'Are you a Blockchain Pioneer?'

const ConnectModalEVM = React.memo(({ isShow, onHide }: IProps)=> {
const dispatch = useAppDispatch()
Expand Down
104 changes: 104 additions & 0 deletions src/components/ConnectModal/modal.modular.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, { useContext } from 'react';
import BaseModal from '@/components/BaseModal';
import { CDN_URL_ICONS } from '@/config';
import { WalletType } from '@/interfaces/wallet';
import styles from './styles.module.scss';
import Image from 'next/image';
import { XVerseContext } from '@/Providers/xverse-context';
import useConnect from '@/hooks/useConnect';
import throttle from 'lodash/throttle'
import { getError } from '@/utils/error';
import toast from 'react-hot-toast';
import { useAppDispatch } from '@/stores/hooks';
import { requestReload } from '@/stores/states/common/reducer';
import AppLoading from '@/components/AppLoading';
import cs from 'classnames';
import { signMessage } from '@/utils/metamask-helper';
import celestiaHelper, { ModularType } from '@/utils/celestia';
import { verifyCelestiaSignature } from '@/services/whitelist';

interface IProps {
isShow: boolean;
onHide: () => void;
}

interface ModalItem {
image: string;
text: string;
type: ModularType
}
const ITEMS: ModalItem[] = [
{
image: `${CDN_URL_ICONS}/kelpr.png`,
text: 'Kelpr',
type: ModularType.kelpr
},
{
image: `${CDN_URL_ICONS}/leap.jpeg`,
text: 'Leap',
type: ModularType.leap
},
];


const ConnectModalModular = React.memo(({ isShow, onHide }: IProps)=> {
const dispatch = useAppDispatch()

const [loading, setLoading] = React.useState(false)

const onSignMessage = async (item: ModalItem) => {
try {
if (loading) return;
const { signature, address } = await celestiaHelper.signCelestiaMessage(item.type);
await verifyCelestiaSignature({ address, signature })
setLoading(true)
dispatch(requestReload());
toast.success("Successfully.")
onHide()
} catch (error) {
const { message } = getError(error);
toast.error(message)
} finally {
setLoading(false)
}
}

const throttleSignMessage = React.useCallback(throttle(onSignMessage, 300), [loading])

const renderItem = React.useCallback(
(item: ModalItem) => {
return (
<div
className={styles.modalItem}
key={item.text}
onClick={() => throttleSignMessage(item)}
>
<Image width={48} height={48} src={item.image} style={{ borderRadius: 120 }} alt="ic_wallet" />
<div className={styles.modalItem_content}>
<p className={styles.modalItem_title}>
{item.text}
</p>
</div>
</div>
);
},
[loading]
);

return (
<BaseModal isShow={isShow} onHide={onHide} title="Choose wallet" size="small">
<div className={cs(styles.modalContent, loading && styles.modalContent__loading)}>
{ITEMS.map(renderItem)}
</div>
{
loading && (
<AppLoading className={styles.loading}/>
)
}
</BaseModal>
);
})

ConnectModalModular.displayName = 'ConnectModalModular';

export default ConnectModalModular;
20 changes: 5 additions & 15 deletions src/modules/Whitelist/steps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
requestClaimBTCPoint,
requestClaimCelestiaPoint,
setBearerToken,
verifyCelestiaSignature,
} from '@/services/whitelist';
import ConnectModal from '@/components/ConnectModal';
import useToggle from '@/hooks/useToggle';
Expand All @@ -24,11 +23,9 @@ import VerifyTwModal from '@/modules/Whitelist/steps/VerifyTwModal';
import ConnectModalEVM from '@/components/ConnectModal/modal.evm';
import useFormatAllowBTC from '@/modules/Whitelist/AllowBTCMessage/useFormatAllowBTC';
import { formatCurrency } from '@/utils/format';
import keplrCelestiaHelper from '@/utils/keplr.celestia';
import { getError } from '@/utils/error';
import toast from 'react-hot-toast';
import useFormatAllowCelestia from '@/modules/Whitelist/AllowCelestiaMessage/useFormatAllowCelestia';
import BigNumber from 'bignumber.js';
import ConnectModalModular from '@/components/ConnectModal/modal.modular';

interface IAuthenCode {
public_code: string;
Expand All @@ -45,6 +42,7 @@ const Steps = () => {
const token = AuthenStorage.getAuthenKey();
const { toggle: isShowConnect, onToggle: onToggleConnect } = useToggle();
const { toggle: isShowConnectEVM, onToggle: onToggleConnectEVM } = useToggle();
const { toggle: isShowConnectModular, onToggle: onToggleConnectModular } = useToggle();
const allowBTC = useFormatAllowBTC()
const allowCelestia = useFormatAllowCelestia()

Expand Down Expand Up @@ -85,15 +83,7 @@ const Steps = () => {
}

const onSignModular = async () => {
try {
const { address, signature } = await keplrCelestiaHelper.signCelestiaMessage();
await verifyCelestiaSignature({ address, signature });
dispatch(requestReload());
toast.success("Successfully.")
} catch (error) {
const { message } = getError(error);
toast.error(message)
}
onToggleConnectModular();
}

const handleShareRefferal = () => {
Expand Down Expand Up @@ -202,7 +192,7 @@ const Steps = () => {
},
{
title: 'Are you a Modular Blockchain Pioneer?',
desc: 'The more TIA or staked TIA you hold, the more points you’ll get. Connect your Keplr wallet to prove the account ownership.',
desc: 'The more TIA or staked TIA you hold, the more points you’ll get. Connect your Keplr or Leap wallet to prove the account ownership.',
actionText: isNeedClaimCelestiaPoint ? `Tweet to claim ${formatCurrency(allowCelestia.amount.unClaimedPoint, 0, 0)} pts` : 'How modular are you?',
actionHandle: isNeedClaimCelestiaPoint ? async () => {
onShareModular();
Expand Down Expand Up @@ -269,6 +259,7 @@ const Steps = () => {
})}
<ConnectModal isShow={isShowConnect} onHide={onToggleConnect}/>
<ConnectModalEVM isShow={isShowConnectEVM} onHide={onToggleConnectEVM}/>
<ConnectModalModular isShow={isShowConnectModular} onHide={onToggleConnectModular}/>
<VerifyTwModal
isShow={showManualCheck}
onHide={() => {
Expand All @@ -277,7 +268,6 @@ const Steps = () => {
secretCode={authenCode?.secret_code}
onSuccess={onVerifyTwSuccess}
/>
{/*<Button onClick={onSignModular}>TEST CELESTIA</Button>*/}
</Flex>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/services/whitelist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ILeaderBoardPoint } from '@/interfaces/leader-board-point';
import createAxiosInstance from './http-client';
import AuthenStorage from '@/utils/storage/authen.storage';
import { SignatureStatus } from '@/interfaces/whitelist';
import keplrCelestiaHelper, { CelestiaAddress, CelestiaSignature } from '@/utils/keplr.celestia';
import celestiaHelper, { CelestiaAddress, CelestiaSignature } from '@/utils/celestia';

const apiClient = createAxiosInstance({
baseURL: `${PERP_API_URL}/api`,
Expand Down Expand Up @@ -100,7 +100,7 @@ const requestClaimCelestiaPoint = async (status: SignatureStatus[]) => {
const verifyCelestiaSignature = async (params: { address: CelestiaAddress, signature: CelestiaSignature }) => {
const res = (await apiClient.post(`/bvm/verify-celestia-address`, {
address: params.address.bech32Address,
message: keplrCelestiaHelper.KeplrCelestiaConfig.messageForSign,
message: celestiaHelper.CelestiaConfig.messageForSign,
signature: params.signature.signature,
pub_key: params.signature.pub_key.value,
})) as any;
Expand Down
62 changes: 45 additions & 17 deletions src/utils/keplr.celestia.ts → src/utils/celestia.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
const KeplrCelestiaConfig = {
const CelestiaConfig = {
chainId: 'celestia',
chainName: 'Celestia',
rpc: 'https://rpc.lunaroasis.net/',
rest: 'https://api.lunaroasis.net/',
messageForSign: 'Are you a Modular Blockchain Pioneer?'
};

export enum ModularType {
kelpr,
leap
}

export interface CelestiaAddress {
bech32Address: string;
algo: string;
Expand All @@ -23,6 +28,14 @@ export interface CelestiaSignature {
}

const getKeplrProvider = () => (window as any)?.keplr;
const getLeapProvider = () => {
const provider = (window as any)?.leap;
if (!provider) {
window.open('https://www.leapwallet.io/#inpage-download')
throw new Error('Please install leap extension')
}
return provider;
};

const addOrSwitchToCelestia = async () => {
const keplr = getKeplrProvider()
Expand All @@ -33,10 +46,10 @@ const addOrSwitchToCelestia = async () => {
if (keplr.experimentalSuggestChain) {
try {
await keplr.experimentalSuggestChain({
chainId: KeplrCelestiaConfig.chainId,
chainName: KeplrCelestiaConfig.chainName,
rpc: KeplrCelestiaConfig.rpc,
rest: KeplrCelestiaConfig.rest,
chainId: CelestiaConfig.chainId,
chainName: CelestiaConfig.chainName,
rpc: CelestiaConfig.rpc,
rest: CelestiaConfig.rest,
bip44: {
coinType: 118,
},
Expand Down Expand Up @@ -80,34 +93,49 @@ const addOrSwitchToCelestia = async () => {
alert("Failed to suggest the chain");
}
}
const chainId = KeplrCelestiaConfig.chainId;
const chainId = CelestiaConfig.chainId;
// Enabling before using the Keplr is recommended.
// This method will ask the user whether to allow access if they haven't visited this website.
// Also, it will request that the user unlock the wallet if the wallet is locked.
await keplr.enable(chainId);
}
}

const signCelestiaMessage = async () => {
const keplr = getKeplrProvider();
await addOrSwitchToCelestia();
const address = (await keplr.getKey(KeplrCelestiaConfig.chainId)) as CelestiaAddress;
const signature = (await keplr.signArbitrary(
KeplrCelestiaConfig.chainId,
const signCelestiaMessage = async (type: ModularType) => {
let provider = undefined;

switch (type) {
case ModularType.kelpr:
provider = getKeplrProvider();
await addOrSwitchToCelestia();
break;
case ModularType.leap:
provider = getLeapProvider()
break;
}

if (!provider) throw Error("Please install wallet.");

const address = (await provider.getKey(CelestiaConfig.chainId)) as CelestiaAddress;

const signature = (await provider.signArbitrary(
CelestiaConfig.chainId,
address.bech32Address,
KeplrCelestiaConfig.messageForSign
CelestiaConfig.messageForSign
)) as CelestiaSignature;

return {
address,
signature
}
}

const keplrCelestiaHelper = {
KeplrCelestiaConfig,
const celestiaHelper = {
CelestiaConfig,
addOrSwitchToCelestia,
getKeplrProvider,
signCelestiaMessage
getLeapProvider,
signCelestiaMessage,
};

export default keplrCelestiaHelper;
export default celestiaHelper;

0 comments on commit 0674033

Please sign in to comment.