Files
explore/ui/address/contract/methods/useCallMethodWalletClient.ts
T
tom goriunovandGitHub ca4c8d6633 OP Superchain Explorer: MVP (#2786)
* context for storing subchain config and tx view for subchain

* address page and block page for subchain

* address aggregated page: local txs tab

* connect MultichainSelect to context

* home page placeholder

* refactor subchain select state

* envs for demo

* fix ts

* clear value for l2 review

* subchain widgets on home page

* csp policies

* sockets, duck and goose

* fix socket on subchain address page

* link builder for subchain views

* update home widget

* fix time increment

* enable tx interpretator and metadata service

* generate multichain config based on every chain app config

* Fix the multichain config to work in Docker

* multichain socket test

* rename subchain-id to subchain-slug path param

* refactoring

* update chain icons on entities

* home page: latest local txs

* latest cross-chain txs

* minor improvements

* renaming, pt. 1

* rename chain routes

* enable blockchain interaction

* add loading state to icon shield

* fix build

* fix tests

* update types package
2025-07-03 15:07:00 +02:00

90 lines
3.1 KiB
TypeScript

import React from 'react';
import { getAddress, type Abi } from 'viem';
import { useAccount, useWalletClient, useSwitchChain } from 'wagmi';
import type { FormSubmitResult, SmartContractMethod } from './types';
import config from 'configs/app';
import { useMultichainContext } from 'lib/contexts/multichain';
import useRewardsActivity from 'lib/hooks/useRewardsActivity';
import { getNativeCoinValue } from './utils';
interface Params {
item: SmartContractMethod;
args: Array<unknown>;
addressHash: string;
}
export default function useCallMethodWalletClient(): (params: Params) => Promise<FormSubmitResult> {
const multichainContext = useMultichainContext();
const chainConfig = (multichainContext?.chain.config ?? config).chain;
const { data: walletClient } = useWalletClient({ chainId: Number(chainConfig.id) });
const { isConnected, chainId, address: account } = useAccount();
const { switchChainAsync } = useSwitchChain();
const { trackTransaction, trackTransactionConfirm } = useRewardsActivity();
return React.useCallback(async({ args, item, addressHash }) => {
if (!isConnected) {
throw new Error('Wallet is not connected');
}
if (!walletClient) {
throw new Error('Wallet Client is not defined');
}
if (chainId && String(chainId) !== chainConfig.id) {
await switchChainAsync({ chainId: Number(chainConfig.id) });
}
const address = getAddress(addressHash);
const activityResponse = await trackTransaction(account ?? '', address);
if (item.type === 'receive' || item.type === 'fallback') {
const value = getNativeCoinValue(args[0]);
const hash = await walletClient.sendTransaction({
to: address,
value,
});
if (activityResponse?.token) {
await trackTransactionConfirm(hash, activityResponse.token);
}
return { source: 'wallet_client', data: { hash } };
}
const methodName = item.name;
if (!methodName) {
throw new Error('Method name is not defined');
}
const _args = args.slice(0, item.inputs.length);
const value = getNativeCoinValue(args[item.inputs.length]);
const hash = await walletClient.writeContract({
args: _args,
// Here we provide the ABI as an array containing only one item from the submitted form.
// This is a workaround for the issue with the "viem" library.
// It lacks a "method_id" field to uniquely identify the correct method and instead attempts to find a method based on its name.
// But the name is not unique in the contract ABI and this behavior in the "viem" could result in calling the wrong method.
// See related issues:
// - https://github.com/blockscout/frontend/issues/1032,
// - https://github.com/blockscout/frontend/issues/1327
abi: [ item ] as Abi,
functionName: methodName,
address,
value,
account,
});
if (activityResponse?.token) {
await trackTransactionConfirm(hash, activityResponse.token);
}
return { source: 'wallet_client', data: { hash } };
}, [ chainId, chainConfig, isConnected, switchChainAsync, walletClient, account, trackTransaction, trackTransactionConfirm ]);
}