Add wallet connect provider for making payments

This commit is contained in:
Shreerang Kale 2024-10-24 17:44:17 +05:30 committed by IshaVenikar
parent df6a492d07
commit 3033e75a9e
4 changed files with 215 additions and 8 deletions

View File

@ -22,6 +22,7 @@ import { useToast } from 'components/shared/Toast';
import { useGQLClient } from '../../../context/GQLClientContext'; import { useGQLClient } from '../../../context/GQLClientContext';
import EnvironmentVariablesForm from 'pages/org-slug/projects/id/settings/EnvironmentVariablesForm'; import EnvironmentVariablesForm from 'pages/org-slug/projects/id/settings/EnvironmentVariablesForm';
import { EnvironmentVariablesFormValues } from 'types/types'; import { EnvironmentVariablesFormValues } from 'types/types';
import { useWalletConnectClient } from 'context/WalletConnectContext';
type ConfigureDeploymentFormValues = { type ConfigureDeploymentFormValues = {
option: string; option: string;
@ -34,6 +35,8 @@ type ConfigureFormValues = ConfigureDeploymentFormValues &
EnvironmentVariablesFormValues; EnvironmentVariablesFormValues;
const Configure = () => { const Configure = () => {
const { onConnect } = useWalletConnectClient()
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [deployers, setDeployers] = useState<Deployer[]>([]); const [deployers, setDeployers] = useState<Deployer[]>([]);
@ -349,6 +352,7 @@ const Configure = () => {
</div> </div>
</form> </form>
</FormProvider> </FormProvider>
<Button onClick={onConnect}>Connect Wallet</Button>
</div> </div>
</div> </div>
); );

View File

@ -0,0 +1,193 @@
import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
import SignClient from '@walletconnect/sign-client';
import { getSdkError } from '@walletconnect/utils';
import { SessionTypes } from '@walletconnect/types';
import { StargateClient } from '@cosmjs/stargate';
import { walletConnectModal } from '../utils/web3modal';
import { VITE_WALLET_CONNECT_ID } from 'utils/constants';
interface ClientInterface {
signClient: SignClient | undefined;
session: SessionTypes.Struct | undefined;
loadingSession: boolean;
onConnect: () => Promise<void>;
onDisconnect: () => Promise<void>;
onSessionDelete: () => void;
accounts: {address: string, balance?: string}[] | undefined;
}
const ClientContext = createContext({} as ClientInterface);
export const useWalletConnectClient = () => {
return useContext(ClientContext);
};
export const WalletConnectClientProvider = ({ children }: {children: JSX.Element}) => {
const [signClient, setSignClient] = useState<SignClient>();
const [session, setSession] = useState<SessionTypes.Struct>();
const [loadingSession, setLoadingSession] = useState(true);
const [accounts, setAccounts] = useState<{address: string, balance?: string}[]>();
const isSignClientInitializing = useRef<boolean>(false);
const createCosmosClient = useCallback(async (endpoint: string) => {
return await StargateClient.connect(endpoint);
}, []);
const onSessionConnect = useCallback(async(session: SessionTypes.Struct) => {
setSession(session);
}, []);
useEffect(()=>{
console.log(accounts)
}, [accounts])
const subscribeToEvents = useCallback(
async (client: SignClient) => {
client.on('session_update', ({ topic, params }) => {
const { namespaces } = params;
const currentSession = client.session.get(topic);
const updatedSession = { ...currentSession, namespaces };
setSession(updatedSession);
});},
[setSession]
);
const onConnect = async () => {
console.log({signClient})
try {
const { uri, approval } = await signClient!.connect({});
console.log({uri})
console.log({uri})
if (uri) {
walletConnectModal.openModal({ uri });
const session = await approval();
onSessionConnect(session);
walletConnectModal.closeModal();
}
} catch (e) {
console.error(e);
}
};
const onDisconnect = useCallback(async () => {
if (typeof signClient === 'undefined') {
throw new Error('WalletConnect is not initialized');
}
if (typeof session === 'undefined') {
throw new Error('Session is not connected');
}
await signClient.disconnect({
topic: session.topic,
reason: getSdkError('USER_DISCONNECTED'),
});
onSessionDelete();
}, [signClient, session]);
const onSessionDelete = () => {
setAccounts(undefined);
setSession(undefined);
};
const checkPersistedState = useCallback(
async (signClient: SignClient) => {
if (typeof signClient === 'undefined') {
throw new Error('WalletConnect is not initialized');
}
if (typeof session !== 'undefined') return;
if (signClient.session.length) {
const lastKeyIndex = signClient.session.keys.length - 1;
const previousSsession = signClient.session.get(
signClient.session.keys[lastKeyIndex]
);
await onSessionConnect(previousSsession);
return previousSsession;
}
},[session, onSessionConnect]);
const createClient = useCallback( async () => {
isSignClientInitializing.current = true;
try{
const signClient = await SignClient.init({
projectId: VITE_WALLET_CONNECT_ID,
metadata: {
name: 'Laconic Pay',
description: 'App for payments',
url: window.location.href,
icons: ['https://avatars.githubusercontent.com/u/92608123']
}
});
setSignClient(signClient);
await checkPersistedState(signClient);
await subscribeToEvents(signClient);
setLoadingSession(false);
} catch(e) {
console.error('error in createClient', e);
}
isSignClientInitializing.current = false;
}, [setSignClient, checkPersistedState, subscribeToEvents]);
useEffect(() => {
if (!signClient && !isSignClientInitializing.current) {
createClient();
}
}, [signClient, createClient]);
useEffect(() => {
const populateAccounts = async () => {
if (!session) {
return;
}
const cosmosAddresses = session.namespaces['cosmos'].accounts;
const cosmosAccounts = cosmosAddresses.map((address) => ({
address,
}));
const allAccounts = cosmosAccounts;
setAccounts(allAccounts);
};
populateAccounts();
}, [session, createCosmosClient]);
useEffect(() => {
if(!signClient){
return;
}
signClient.on('session_delete', onSessionDelete);
return () => {
signClient.off('session_delete', onSessionDelete);
};
});
return (
<ClientContext.Provider
value=
{{
signClient,
onConnect,
onDisconnect,
onSessionDelete,
loadingSession,
session,
accounts,
}}
>
{children}
</ClientContext.Provider>
);
};

View File

@ -16,6 +16,7 @@ import { Toaster } from 'components/shared/Toast';
import { LogErrorBoundary } from 'utils/log-error'; import { LogErrorBoundary } from 'utils/log-error';
import { BASE_URL } from 'utils/constants'; import { BASE_URL } from 'utils/constants';
import Web3ModalProvider from './context/Web3Provider'; import Web3ModalProvider from './context/Web3Provider';
import { WalletConnectClientProvider } from 'context/WalletConnectContext';
console.log(`v-0.0.9`); console.log(`v-0.0.9`);
@ -31,6 +32,7 @@ const gqlClient = new GQLClient({ gqlEndpoint });
root.render( root.render(
<LogErrorBoundary> <LogErrorBoundary>
<React.StrictMode> <React.StrictMode>
<WalletConnectClientProvider>
<ThemeProvider> <ThemeProvider>
<Web3ModalProvider> <Web3ModalProvider>
<GQLClientProvider client={gqlClient}> <GQLClientProvider client={gqlClient}>
@ -39,6 +41,7 @@ root.render(
</GQLClientProvider> </GQLClientProvider>
</Web3ModalProvider> </Web3ModalProvider>
</ThemeProvider> </ThemeProvider>
</WalletConnectClientProvider>
</React.StrictMode> </React.StrictMode>
</LogErrorBoundary>, </LogErrorBoundary>,
); );

View File

@ -0,0 +1,7 @@
import { WalletConnectModal } from '@walletconnect/modal';
import { VITE_WALLET_CONNECT_ID } from 'utils/constants';
export const walletConnectModal = new WalletConnectModal({
projectId: VITE_WALLET_CONNECT_ID!,
chains:['cosmos:theta-testnet-001']
});