@hyperlane-xyz/widgets
Version:
Common react components for Hyperlane projects
100 lines • 4.28 kB
JavaScript
import { useAccount, useConnect, useDisconnect, useNetwork, useSendTransaction, useSwitchChain, } from '@starknet-react/core';
import { useCallback, useMemo } from 'react';
import { useStarknetkitConnectModal } from 'starknetkit';
import { ProviderType, chainMetadataToStarknetChain, } from '@hyperlane-xyz/sdk';
import { ProtocolType, assert } from '@hyperlane-xyz/utils';
import { widgetLogger } from '../logger.js';
import { getChainsForProtocol } from './utils.js';
const logger = widgetLogger.child({
module: 'widgets/walletIntegrations/starknet',
});
export function useStarknetAccount(_multiProvider) {
const { address, isConnected } = useAccount();
return useMemo(() => ({
protocol: ProtocolType.Starknet,
addresses: address ? [{ address }] : [],
isReady: !!isConnected,
}), [address, isConnected]);
}
export function useStarknetWalletDetails() {
const { connector } = useAccount();
return useMemo(() => ({
name: connector?.id || 'Starknet Wallet',
logoUrl: typeof connector?.icon === 'string'
? connector.icon
: connector?.icon?.light,
}), [connector]);
}
export function useStarknetConnectFn() {
const { connectAsync, connectors } = useConnect();
// This is how they do it: https://github.com/argentlabs/starknetkit-example-dapp/blob/d1d5ba8b5e06eef76b9df9b01832b57d2f22c649/src/components/connect/ConnectStarknetReactNext.tsx#L21
const { starknetkitConnectModal } = useStarknetkitConnectModal({
connectors: connectors,
});
return useCallback(async () => {
const { connector } = await starknetkitConnectModal();
if (connector) {
await connectAsync({ connector });
}
else {
logger.error('No Starknet wallet connectors available');
}
}, [connectAsync, starknetkitConnectModal]);
}
export function useStarknetDisconnectFn() {
const { disconnectAsync } = useDisconnect();
return disconnectAsync;
}
export function useStarknetActiveChain(_multiProvider) {
const { chain } = useNetwork();
return useMemo(() => ({
chainDisplayName: chain?.name,
chainName: chain?.id ? chain.id.toString() : undefined,
}), [chain]);
}
export function useStarknetTransactionFns(multiProvider) {
const { account } = useAccount();
const { sendAsync } = useSendTransaction({});
const { switchChainAsync } = useSwitchChain({});
const onSwitchNetwork = useCallback(async (chainName) => {
const chainId = multiProvider.getChainMetadata(chainName).chainId;
await switchChainAsync({
chainId: chainId.toString(),
});
}, [multiProvider, switchChainAsync]);
const onSendTx = useCallback(async ({ tx, chainName, activeChainName, }) => {
if (tx.type !== ProviderType.Starknet) {
throw new Error(`Invalid transaction type for Starknet: ${tx.type}`);
}
if (activeChainName && activeChainName !== chainName) {
await onSwitchNetwork(chainName);
}
if (!account) {
throw new Error('No StarkNet account connected');
}
const chainId = multiProvider.getChainMetadata(chainName).chainId;
const chainIdFromWallet = await account.getChainId();
try {
assert(chainIdFromWallet === chainId, `Wallet not on chain ${chainName} (ChainMismatchError)`);
const result = await sendAsync([tx.transaction]);
const hash = result.transaction_hash;
const confirm = async () => {
const receipt = await account.waitForTransaction(hash);
return {
type: ProviderType.Starknet,
receipt,
};
};
return { hash, confirm };
}
catch (error) {
logger.error('Failed to send StarkNet transaction:', error);
throw error;
}
}, [account, multiProvider, onSwitchNetwork, sendAsync]);
return { sendTransaction: onSendTx, switchNetwork: onSwitchNetwork };
}
export function getStarknetChains(multiProvider) {
return getChainsForProtocol(multiProvider, ProtocolType.Starknet).map(chainMetadataToStarknetChain);
}
//# sourceMappingURL=starknet.js.map