Skip to content

Commit

Permalink
Merge pull request #844 from haqq-network/dev
Browse files Browse the repository at this point in the history
release
  • Loading branch information
kioqq authored May 21, 2024
2 parents 83a71f6 + 2613f2e commit 6df3969
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 115 deletions.
17 changes: 10 additions & 7 deletions apps/shell/src/hooks/use-autoconnect.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
'use client';
import { useEffect } from 'react';
import { useConnect } from 'wagmi';
import { useAccount, useConnect } from 'wagmi';

export function useHaqqWalletAutoConnect() {
const { isConnected } = useAccount();
const { connect, connectors } = useConnect();

useEffect(() => {
const connectorInstance = connectors.find((c) => {
return c.id === 'injected' && c.name.toLowerCase().includes('haqq');
});
if (!isConnected) {
const connectorInstance = connectors.find((c) => {
return c.id === 'injected' && c.name.toLowerCase().includes('haqq');
});

if (connectorInstance) {
connect({ connector: connectorInstance });
if (connectorInstance) {
connect({ connector: connectorInstance });
}
}
}, [connect, connectors]);
}, [connect, connectors, isConnected]);
}
117 changes: 91 additions & 26 deletions libs/shell/shared/src/providers/wallet-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import {
createTxRawEIP712,
TxGenerated,
} from '@evmos/transactions';
import { ec as EC } from 'elliptic';
import { usePostHog } from 'posthog-js/react';
import store from 'store2';
import type { Hex } from 'viem';
import { publicKeyToAddress } from 'viem/utils';
import {
useDisconnect,
useNetwork,
Expand Down Expand Up @@ -62,6 +64,15 @@ const WalletContext = createContext<WalletProviderInterface | undefined>(
undefined,
);

function base64ToUncompressedHex(base64: string): Hex {
const buffer = Buffer.from(base64, 'base64');
const ec = new EC('secp256k1');
const key = ec.keyFromPublic(buffer);
const uncompressed = key.getPublic(false, 'hex');

return `0x${uncompressed}`;
}

export function WalletProvider({ children }: { children: ReactNode }) {
const chains = useSupportedChains();
const { chain = chains[0] } = useNetwork();
Expand Down Expand Up @@ -164,45 +175,99 @@ export function WalletProvider({ children }: { children: ReactNode }) {
[walletClient],
);

const validatePubkey = useCallback((address: string, pubkey: string) => {
try {
const pkUncompressedHex = base64ToUncompressedHex(pubkey);
const recoveredAddress = publicKeyToAddress(pkUncompressedHex);

return address.toLowerCase() === recoveredAddress.toLowerCase();
} catch (error) {
console.error('Failed to validate pubkey');
return false;
}
}, []);

const fetchPubkey = useCallback(
async (address: string) => {
const haqqAddress = ethToHaqq(address);
let pubkey = await getPubkeyFromChain(haqqAddress);

if (!pubkey) {
pubkey = await generatePubkey(address);
}

return pubkey;
},
[generatePubkey, getPubkeyFromChain],
);

const getPubkey = useCallback(
async (address: string) => {
posthog.capture('get pubkey start', {
chaidId: haqqChain.chainId,
});
const storeKey = `pubkey_${address}`;
const savedPubKey: string | null = store.get(storeKey);
// console.log('getPubkey', { storeKey, savedPubKey });

if (!savedPubKey) {
try {
let pubkey: string | undefined;
const haqqAddress = ethToHaqq(address);
pubkey = await getPubkeyFromChain(haqqAddress);
try {
posthog.capture('get pubkey start', {
chaidId: haqqChain.chainId,
address,
});

let savedPubKey: string | null = store.get(storeKey);

if (!pubkey) {
pubkey = await generatePubkey(address);
}
if (!savedPubKey) {
const pubkey = await fetchPubkey(address);

store.set(storeKey, pubkey);
return pubkey;
} catch (error) {
const message = (error as Error).message;
posthog.capture('get pubkey failed', {
savedPubKey = pubkey;
}

const isValid = validatePubkey(address, savedPubKey);

if (!isValid) {
store.remove(storeKey);

const pubkey = await fetchPubkey(address);

store.set(storeKey, pubkey);

const isValidAfterRetry = validatePubkey(address, pubkey);

if (!isValidAfterRetry) {
const errorMessage = 'Invalid public key after retry';
posthog.capture('get pubkey failed', {
chaidId: haqqChain.chainId,
address,
error: errorMessage,
});
console.error(errorMessage);
throw new Error(errorMessage);
}

posthog.capture('get pubkey success', {
chaidId: haqqChain.chainId,
error: message,
address,
});
console.error(message);
throw error;

return pubkey;
}
}

posthog.capture('get pubkey success', {
chaidId: haqqChain.chainId,
});
posthog.capture('get pubkey success', {
chaidId: haqqChain.chainId,
address,
});

return savedPubKey;
return savedPubKey;
} catch (error) {
const message = (error as Error).message;
posthog.capture('get pubkey failed', {
chaidId: haqqChain.chainId,
address,
error: message,
});
console.error(message);
throw error;
}
},
[generatePubkey, getPubkeyFromChain, haqqChain.chainId, posthog],
[fetchPubkey, haqqChain.chainId, posthog, validatePubkey],
);

const signTransaction = useCallback(
Expand Down
64 changes: 37 additions & 27 deletions libs/shell/staking/src/lib/components/delegate-modal-hooked.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,35 +75,43 @@ export function DelegateModalHooked({
fee,
);

await toast.promise(delegationPromise, {
loading: <ToastLoading>Delegation in progress</ToastLoading>,
success: (tx) => {
console.log('Delegation successful', { tx });
const txHash = tx?.txhash;
await toast.promise(
delegationPromise,
{
loading: <ToastLoading>Delegation in progress</ToastLoading>,
success: (tx) => {
console.log('Delegation successful', { tx });
const txHash = tx?.txhash;

return (
<ToastSuccess>
<div className="flex flex-col items-center gap-[8px] text-[20px] leading-[26px]">
<div>Delegation successful</div>
<div>
<Link
href={`${explorer.cosmos}/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
className="text-haqq-orange hover:text-haqq-light-orange flex items-center gap-[4px] lowercase transition-colors duration-300"
>
<LinkIcon />
<span>{getFormattedAddress(txHash)}</span>
</Link>
return (
<ToastSuccess>
<div className="flex flex-col items-center gap-[8px] text-[20px] leading-[26px]">
<div>Delegation successful</div>
<div>
<Link
href={`${explorer.cosmos}/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
className="text-haqq-orange hover:text-haqq-light-orange flex items-center gap-[4px] lowercase transition-colors duration-300"
>
<LinkIcon />
<span>{getFormattedAddress(txHash)}</span>
</Link>
</div>
</div>
</div>
</ToastSuccess>
);
</ToastSuccess>
);
},
error: (error) => {
return <ToastError>{error.message}</ToastError>;
},
},
error: (error) => {
return <ToastError>{error.message}</ToastError>;
{
success: {
duration: 5000,
},
},
});
);
posthog.capture('delegate success', { chainId });
onClose();
} catch (error) {
Expand Down Expand Up @@ -179,8 +187,9 @@ export function DelegateModalHooked({
setFeePending(false);
}
})
.catch((reason) => {
console.error(reason);
.catch((error) => {
const message = (error as Error).message;
toast.error(<ToastError>{message}</ToastError>);
setFeePending(false);
});
}
Expand All @@ -191,6 +200,7 @@ export function DelegateModalHooked({
isDelegateEnabled,
validatorAddress,
cancelPreviousRequest,
toast,
]);

return (
Expand Down
66 changes: 38 additions & 28 deletions libs/shell/staking/src/lib/components/redelegate-modal-hooked.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,35 +77,43 @@ export function RedelegateModalHooked({
fee,
);

await toast.promise(redelegationPromise, {
loading: <ToastLoading>Redelegate in progress</ToastLoading>,
success: (tx) => {
console.log('Redelegation successful', { tx });
const txHash = tx?.txhash;

return (
<ToastSuccess>
<div className="flex flex-col items-center gap-[8px] text-[20px] leading-[26px]">
<div>Redelegation successful</div>
<div>
<Link
href={`${explorer.cosmos}/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
className="text-haqq-orange hover:text-haqq-light-orange flex items-center gap-[4px] lowercase transition-colors duration-300"
>
<LinkIcon />
<span>{getFormattedAddress(txHash)}</span>
</Link>
await toast.promise(
redelegationPromise,
{
loading: <ToastLoading>Redelegate in progress</ToastLoading>,
success: (tx) => {
console.log('Redelegation successful', { tx });
const txHash = tx?.txhash;

return (
<ToastSuccess>
<div className="flex flex-col items-center gap-[8px] text-[20px] leading-[26px]">
<div>Redelegation successful</div>
<div>
<Link
href={`${explorer.cosmos}/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
className="text-haqq-orange hover:text-haqq-light-orange flex items-center gap-[4px] lowercase transition-colors duration-300"
>
<LinkIcon />
<span>{getFormattedAddress(txHash)}</span>
</Link>
</div>
</div>
</div>
</ToastSuccess>
);
</ToastSuccess>
);
},
error: (error) => {
return <ToastError>{error.message}</ToastError>;
},
},
error: (error) => {
return <ToastError>{error.message}</ToastError>;
{
success: {
duration: 5000,
},
},
});
);
posthog.capture('redelegate success', { chainId });
onClose();
}
Expand Down Expand Up @@ -206,8 +214,9 @@ export function RedelegateModalHooked({
setFeePending(false);
}
})
.catch((reason) => {
console.error(reason);
.catch((error) => {
const message = (error as Error).message;
toast.error(<ToastError>{message}</ToastError>);
setFeePending(false);
});
}
Expand All @@ -219,6 +228,7 @@ export function RedelegateModalHooked({
validatorDestinationAddress,
getRedelegateEstimatedFee,
isRedelegateEnabled,
toast,
]);

return (
Expand Down
Loading

0 comments on commit 6df3969

Please sign in to comment.