diff --git a/examples/hello/frontend/package.json b/examples/hello/frontend/package.json
index 670a41f3..5757f5c0 100644
--- a/examples/hello/frontend/package.json
+++ b/examples/hello/frontend/package.json
@@ -10,8 +10,8 @@
"preview": "vite preview"
},
"dependencies": {
- "@zetachain/toolkit": "16.1.3",
- "@zetachain/wallet": "1.0.12",
+ "@zetachain/toolkit": "16.1.4",
+ "@zetachain/wallet": "1.0.13",
"clsx": "^2.1.1",
"ethers": "^6.13.2",
"react": "^19.1.0",
diff --git a/examples/hello/frontend/src/ConfirmedContent.tsx b/examples/hello/frontend/src/ConfirmedContent.tsx
index 30f4e702..7d5122c2 100644
--- a/examples/hello/frontend/src/ConfirmedContent.tsx
+++ b/examples/hello/frontend/src/ConfirmedContent.tsx
@@ -79,7 +79,7 @@ export function ConfirmedContent({
{!connectedChainTxHash &&
}
{!zetachainTxHash && }
{
const { switchChain } = useDynamicSwitchChainHook();
+ const userWallets = useUserWallets();
+ const switchWallet = useSwitchWallet();
+
+ const primaryWalletChain = primaryWallet?.chain;
+ const walletIds: Record = useMemo(() => {
+ const solanaWallet = userWallets.find(
+ (wallet) => wallet.chain === 'SOL'
+ )?.id;
+ const evmWallet = userWallets.find((wallet) => wallet.chain === 'EVM')?.id;
+
+ return {
+ EVM: evmWallet || '',
+ SOL: solanaWallet || '',
+ };
+ }, [userWallets]);
const handleNetworkSelect = (chain: SupportedChain) => {
+ // We only switch wallet if the chain type is
+ // different from the primary wallet chain (i.e.: EVM -> SOL)
+ if (chain.chainType !== primaryWalletChain) {
+ switchWallet(walletIds[chain.chainType]);
+ }
+
switchChain(chain.chainId);
};
@@ -60,7 +84,7 @@ const DynamicConnectedContent = ({
const Eip6963ConnectedContent = ({
selectedProvider,
supportedChain,
- primaryWallet,
+ account,
}: ConnectedContentProps) => {
const { switchChain } = useSwitchChain();
@@ -89,7 +113,7 @@ const Eip6963ConnectedContent = ({
@@ -101,6 +125,7 @@ export function ConnectedContent({
selectedProvider,
supportedChain,
primaryWallet,
+ account,
}: ConnectedContentProps) {
return USE_DYNAMIC_WALLET ? (
);
}
diff --git a/examples/hello/frontend/src/DynamicAppContent.tsx b/examples/hello/frontend/src/DynamicAppContent.tsx
index cda54c54..5981418a 100644
--- a/examples/hello/frontend/src/DynamicAppContent.tsx
+++ b/examples/hello/frontend/src/DynamicAppContent.tsx
@@ -1,4 +1,5 @@
import { useUniversalSignInContext } from '@zetachain/wallet/react';
+import { useMemo } from 'react';
import { ConnectedContent } from './ConnectedContent';
import { SUPPORTED_CHAINS } from './constants/chains';
@@ -8,7 +9,18 @@ export function DynamicAppContent() {
const { primaryWallet, network } = useUniversalSignInContext();
const account = primaryWallet?.address || null;
- const decimalChainId = network || null;
+ const decimalChainId = useMemo(() => {
+ if (typeof network === 'number') {
+ return network;
+ }
+
+ // Solana Devnet id from `network` property
+ if (network === '103') {
+ return 901;
+ }
+
+ return null;
+ }, [network]);
const supportedChain = SUPPORTED_CHAINS.find(
(chain) => chain.chainId === decimalChainId
@@ -27,4 +39,4 @@ export function DynamicAppContent() {
primaryWallet={primaryWallet}
/>
);
-}
\ No newline at end of file
+}
diff --git a/examples/hello/frontend/src/Eip6963AppContent.tsx b/examples/hello/frontend/src/Eip6963AppContent.tsx
index 5344197b..b6b9035b 100644
--- a/examples/hello/frontend/src/Eip6963AppContent.tsx
+++ b/examples/hello/frontend/src/Eip6963AppContent.tsx
@@ -4,7 +4,7 @@ import { DisconnectedContent } from './DisconnectedContent';
import { useEip6963Wallet } from './hooks/useEip6963Wallet';
export function Eip6963AppContent() {
- const { selectedProvider, decimalChainId } = useEip6963Wallet();
+ const { selectedProvider, decimalChainId, account } = useEip6963Wallet();
const supportedChain = SUPPORTED_CHAINS.find(
(chain) => chain.chainId === decimalChainId
@@ -20,6 +20,7 @@ export function Eip6963AppContent() {
);
-}
\ No newline at end of file
+}
diff --git a/examples/hello/frontend/src/MessageFlowCard.tsx b/examples/hello/frontend/src/MessageFlowCard.tsx
index 9a7fbabc..9a0a973b 100644
--- a/examples/hello/frontend/src/MessageFlowCard.tsx
+++ b/examples/hello/frontend/src/MessageFlowCard.tsx
@@ -1,8 +1,6 @@
import './MessageFlowCard.css';
-import { evmCall } from '@zetachain/toolkit/chains/evm';
import { type PrimaryWallet } from '@zetachain/wallet';
-import { ZeroAddress } from 'ethers';
import { useEffect, useRef, useState } from 'react';
import { Button } from './components/Button';
@@ -10,22 +8,23 @@ import { IconApprove, IconEnvelope, IconSendTitle } from './components/icons';
import { ConfirmedContent } from './ConfirmedContent';
import type { SupportedChain } from './constants/chains';
import { HELLO_UNIVERSAL_CONTRACT_ADDRESS } from './constants/contracts';
+import { useHandleCall } from './hooks/useHandleCall';
import type { EIP6963ProviderDetail } from './types/wallet';
-import { getSignerAndProvider } from './utils/ethersHelpers';
import { formatNumberWithLocale } from './utils/formatNumber';
interface MessageFlowCardProps {
selectedProvider: EIP6963ProviderDetail | null;
supportedChain: SupportedChain | undefined;
primaryWallet?: PrimaryWallet | null; // Dynamic wallet from context
+ account?: string | null; // EIP6963 account for non-dynamic route
}
export function MessageFlowCard({
selectedProvider,
supportedChain,
primaryWallet = null,
+ account = null,
}: MessageFlowCardProps) {
-
const MAX_STRING_LENGTH = 2000;
const [isUserSigningTx, setIsUserSigningTx] = useState(false);
const [isTxReceiptLoading, setIsTxReceiptLoading] = useState(false);
@@ -37,55 +36,22 @@ export function MessageFlowCard({
return new TextEncoder().encode(string).length;
};
- const handleEvmCall = async () => {
- try {
- const signerAndProvider = await getSignerAndProvider({
- selectedProvider,
- primaryWallet,
- });
-
- if (!signerAndProvider) {
- throw new Error('Failed to get signer');
- }
-
- const { signer } = signerAndProvider;
-
- const evmCallParams = {
- receiver: HELLO_UNIVERSAL_CONTRACT_ADDRESS,
- types: ['string'],
- values: [stringValue],
- revertOptions: {
- callOnRevert: false,
- revertAddress: ZeroAddress,
- revertMessage: '',
- abortAddress: ZeroAddress,
- onRevertGasLimit: 1000000,
- },
- };
-
- const evmCallOptions = {
- signer,
- txOptions: {
- gasLimit: 1000000,
- },
- };
-
- setIsUserSigningTx(true);
-
- const result = await evmCall(evmCallParams, evmCallOptions);
-
- setIsTxReceiptLoading(true);
-
- await result.wait();
-
- setConnectedChainTxHash(result.hash);
- } catch (error) {
- console.error(error);
- } finally {
+ const { handleCall } = useHandleCall({
+ primaryWallet,
+ selectedProvider,
+ supportedChain,
+ receiver: HELLO_UNIVERSAL_CONTRACT_ADDRESS,
+ message: stringValue,
+ account,
+ onSigningStart: () => setIsUserSigningTx(true),
+ onTransactionSubmitted: () => setIsTxReceiptLoading(true),
+ onTransactionConfirmed: (txHash: string) => setConnectedChainTxHash(txHash),
+ onError: (error: Error) => console.error('Transaction error:', error),
+ onComplete: () => {
setIsUserSigningTx(false);
setIsTxReceiptLoading(false);
- }
- };
+ },
+ });
// Auto-resize textarea based on content
useEffect(() => {
@@ -168,7 +134,7 @@ export function MessageFlowCard({