@megaeth-labs/wallet-sdk-react
v0.1.21
Published
MegaETH Wallet SDK React Wrapper for web applications
Downloads
1,431
Readme
MOSS Wallet SDK (React)
React hooks and components for the MegaETH Wallet SDK, built on top of @megaeth-labs/wallet-sdk and TanStack Query.
Contents
- Install
- Setup
- Connection Management
- Authentication
- Transfers
- Smart Contract Interactions
- Session Keys & Permissions
- Message Signing
- Wallet Information
- Direct SDK Access
Install
npm install @megaeth-labs/wallet-sdk-react @tanstack/react-querySetup
Wrap your application with MegaProvider to initialize the wallet SDK. The provider handles initialization automatically and provides React hooks for all wallet operations.
import { MegaProvider } from '@megaeth-labs/wallet-sdk-react';
function App() {
return (
<MegaProvider
config={{
network: 'mainnet', // or 'testnet'
logging: 'error', // Optional: 'debug' | 'info' | 'warn' | 'error'
debug: false, // Optional: Enable internal verbose debug logging
sponsorUrl: 'https://your-sponsor-url.com', // Optional: Custom sponsor URL
sponsorMode: 'app-only', // Optional: 'everything' | 'app-only' | 'explicit'
sponsorToken: 'native', // Optional: 'native' | 'usdm'
}}
>
<YourApp />
</MegaProvider>
);
}Connection Management
Connect Wallet
Use the useConnect hook to show the connection UI and handle user connection.
import { useConnect } from '@megaeth-labs/wallet-sdk-react';
function ConnectButton() {
const { mutate: connect, isPending } = useConnect({
onSuccess: (result) => {
if (result.status === 'connected') {
console.log('Wallet connected:', result.address);
}
},
});
return (
<button onClick={() => connect()} disabled={isPending}>
{isPending ? 'Connecting...' : 'Connect Wallet'}
</button>
);
}Check Status
Use the useStatus hook to get the current connection status.
import { useStatus } from '@megaeth-labs/wallet-sdk-react';
function WalletStatus() {
const { status, address, initialised } = useStatus();
if (!initialised) return <div>Initializing...</div>;
return (
<div>
Status: {status}
{address && <div>Address: {address}</div>}
</div>
);
}Disconnect
Use the useDisconnect hook to disconnect the current wallet session.
import { useDisconnect } from '@megaeth-labs/wallet-sdk-react';
function DisconnectButton() {
const { mutate: disconnect } = useDisconnect({
onSuccess: () => console.log('Disconnected'),
});
return <button onClick={() => disconnect()}>Disconnect</button>;
}Authentication
Authenticate with SIWE
Use the useAuthenticate hook to show the built-in Sign-In with Ethereum (SIWE) UI. Returns a JWT that can be verified at https://wallet-api.megaeth.com/v1/partner-auth/verify?origin=YOUR_ORIGIN&jwt=JWT_TOKEN
import { useAuthenticate } from '@megaeth-labs/wallet-sdk-react';
function AuthenticateButton() {
const { mutate: authenticate, isPending } = useAuthenticate({
onSuccess: async (auth) => {
if (auth.status === 'success' && auth.jwt) {
const response = await fetch(
`https://wallet-api.megaeth.com/v1/partner-auth/verify?origin=${window.location.host}&jwt=${auth.jwt}`
);
const { walletAddress } = await response.json();
console.log('Authenticated:', walletAddress);
}
},
});
return (
<button onClick={() => authenticate()} disabled={isPending}>
Authenticate
</button>
);
}Transfers
Native Token Transfer (ETH)
Use the useTransfer hook to transfer native tokens from the connected wallet.
import { useTransfer } from '@megaeth-labs/wallet-sdk-react';
import { parseEther } from 'viem';
function TransferButton() {
const { mutate: transfer, isPending } = useTransfer({
onSuccess: (result) => {
if (result.status === 'approved') {
console.log('Transaction hash:', result.receipt.hash);
}
},
});
const handleTransfer = () => {
transfer({
type: 'native',
to: '0xRecipientAddress',
amount: parseEther('0.1').toString(),
sponsor: false, // Optional: Use sponsored transactions when sponsor mode is explicit
});
};
return <button onClick={handleTransfer} disabled={isPending}>Send ETH</button>;
}ERC20 Token Transfer
Transfer ERC20 tokens using the useTransfer hook.
import { useTransfer } from '@megaeth-labs/wallet-sdk-react';
import { parseUnits } from 'viem';
function TransferERC20Button() {
const { mutate: transfer } = useTransfer();
const handleTransfer = () => {
transfer({
type: 'erc20',
to: '0xRecipientAddress',
amount: parseUnits('100', 18).toString(), // 100 tokens with 18 decimals
contractAddress: '0xTokenContractAddress',
});
};
return <button onClick={handleTransfer}>Send Tokens</button>;
}ERC721 NFT Transfer
Transfer an ERC721 NFT.
const { mutate: transfer } = useTransfer();
transfer({
type: 'erc721',
to: '0xRecipientAddress',
contractAddress: '0xNFTContractAddress',
tokenId: 1234,
amount: '0',
});ERC1155 Token Transfer
Transfer ERC1155 tokens.
const { mutate: transfer } = useTransfer();
transfer({
type: 'erc1155',
to: '0xRecipientAddress',
contractAddress: '0xTokenContractAddress',
tokenId: 1,
amount: '5', // Number of tokens to transfer
});Smart Contract Interactions
Call Contract Method
Use the useCallContract hook to execute a contract method with user approval.
import { useCallContract } from '@megaeth-labs/wallet-sdk-react';
import { parseEther } from 'viem';
function MintButton() {
const { mutate: callContract, isPending } = useCallContract({
onSuccess: (result) => {
if (result.status === 'approved') {
console.log('Transaction hash:', result.receipt.hash);
}
},
});
const handleMint = () => {
callContract({
address: '0xContractAddress',
abi: contractABI,
functionName: 'mint',
args: [parseEther('1')],
value: parseEther('0.1'), // Optional: ETH value to send
sponsor: false, // Optional: Use sponsored transactions when sponsor mode is explicit
});
};
return <button onClick={handleMint} disabled={isPending}>Mint</button>;
}Silent Contract Call (Session Keys)
Execute a contract method silently using session key permissions (no user approval required).
const { mutate: callContract } = useCallContract();
callContract({
address: '0xContractAddress',
abi: contractABI,
functionName: 'claim',
args: [],
silent: true, // Uses session key with pre-approved permissions
});Batch Contract Calls
Execute multiple contract calls in a single transaction.
const { mutate: callContract } = useCallContract();
callContract([
{
address: '0xContract1',
abi: abi1,
functionName: 'approve',
args: ['0xSpender', parseEther('100')],
},
{
address: '0xContract2',
abi: abi2,
functionName: 'swap',
args: [parseEther('100')],
},
]);Call Contract with Raw Data
Execute a contract call using raw calldata instead of ABI.
const { mutate: callContract } = useCallContract();
callContract({
address: '0xContractAddress',
data: '0x...' as `0x${string}`,
value: parseEther('0.1'),
});Read from Contract (No Gas)
Use the useGetFromContract hook to read data from a contract without creating a transaction.
import { useGetFromContract } from '@megaeth-labs/wallet-sdk-react';
function BalanceDisplay() {
const { mutate: getFromContract, data: balance } = useGetFromContract();
useEffect(() => {
getFromContract({
address: '0xTokenContract',
abi: erc20ABI,
functionName: 'balanceOf',
args: ['0xUserAddress'],
});
}, []);
return <div>Balance: {balance?.toString()}</div>;
}Session Keys & Permissions
Grant Permissions
Use the useGrantPermissions hook to grant session key permissions for silent transactions. Users approve once, then your app can execute permitted transactions without additional prompts.
import { useGrantPermissions } from '@megaeth-labs/wallet-sdk-react';
import { parseEther } from 'viem';
function GrantPermissionsButton() {
const { mutate: grantPermissions, isPending } = useGrantPermissions({
onSuccess: (result) => {
if (result.status === 'approved') {
console.log('Permissions granted');
}
},
});
const handleGrant = () => {
grantPermissions({
permissions: {
expiry: 86400, // Expiry in seconds (24 hours)
feeToken: {
limit: parseEther('0.01').toString(), // Max fee allowed per transaction
symbol: 'ETH', // Optional: Fee token symbol
},
permissions: {
// Specific contract calls allowed
calls: [
{
to: '0xContractAddress',
signature: 'mint(uint256)', // Function signature
},
{
to: '0xAnotherContract',
signature: 'claim()',
},
],
// Spending limits for tokens
spend: [
{
limit: parseEther('100'), // 100 ETH
period: 'day', // 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
token: undefined, // undefined for native ETH
},
{
limit: parseEther('1000'), // 1000 tokens
period: 'week',
token: '0xTokenAddress' as `0x${string}`,
},
],
},
},
externalAddress: '0xYourAppAddress', // Optional: External address for permissions
sponsor: false, // Optional: Sponsor the permission grant transaction
});
};
return <button onClick={handleGrant} disabled={isPending}>Grant Permissions</button>;
}Get Current Permissions
Use the usePermissions hook to check what permissions are currently active for an address.
import { usePermissions } from '@megaeth-labs/wallet-sdk-react';
function PermissionsDisplay() {
const { data: perms, isLoading } = usePermissions('0xUserAddress'); // Optional: address parameter
if (isLoading) return <div>Loading...</div>;
if (perms?.permissions) {
return (
<div>
<div>Expiry: {new Date(perms.permissions.expiry * 1000).toLocaleString()}</div>
<div>Allowed calls: {perms.permissions.permissions.calls.length}</div>
<div>Spending limits: {perms.permissions.permissions.spend.length}</div>
</div>
);
}
return <div>No permissions found</div>;
}Revoke Permissions
Use the useRevokePermissions hook to revoke all active session key permissions.
import { useRevokePermissions } from '@megaeth-labs/wallet-sdk-react';
function RevokeButton() {
const { mutate: revokePermissions } = useRevokePermissions({
onSuccess: () => console.log('All permissions revoked'),
});
return <button onClick={() => revokePermissions()}>Revoke Permissions</button>;
}Message Signing
Sign Message
Use the useSignMessage hook to request the user to sign a message.
import { useSignMessage } from '@megaeth-labs/wallet-sdk-react';
function SignMessageButton() {
const { mutate: signMessage, data } = useSignMessage({
onSuccess: (result) => {
if (result.status === 'success' && result.signature) {
console.log('Signature:', result.signature);
}
},
});
return <button onClick={() => signMessage('Hello, World!')}>Sign Message</button>;
}Sign Structured Data (EIP-712)
Use the useSignData hook to sign typed structured data.
import { useSignData } from '@megaeth-labs/wallet-sdk-react';
function SignDataButton() {
const { mutate: signData } = useSignData({
onSuccess: (result) => {
if (result.status === 'success' && result.signature) {
console.log('Signature:', result.signature);
}
},
});
const handleSign = () => {
const domain = {
name: 'MyApp',
version: '1',
chainId: 1,
verifyingContract: '0xContract',
};
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' },
],
};
const value = {
name: 'Alice',
wallet: '0x...',
};
signData({
data: { domain, types, value },
});
};
return <button onClick={handleSign}>Sign Data</button>;
}Verifying Messages
For SIWE messages, the @megaeth-labs/wallet-server-verify package can be used to verify the signature.
For other messages or for more control, the following code can be used:
import { PersonalMessage } from 'ox';
import { Porto, RelayActions } from 'porto';
import { RelayClient } from 'porto/viem';
import { http, toBytes } from 'viem';
import { megaeth, megaethTestnet } from 'viem/chains';
const message = 'Hello';
const address = '0x...';
const signature = '0x...';
const chainId = 4326;
const porto = Porto.create({
relay: http('https://wallet-relay.megaeth.com'),
chains: [megaeth, megaethTestnet],
});
const client = RelayClient.fromPorto(porto, {
chainId
});
const result = await RelayActions.verifySignature(client, {
address,
digest: PersonalMessage.getSignPayload(toBytes(message)),
signature
});
if(!result.valid) {
throw new Error('Invalid Signature');
}Wallet Information
Get Token Balances
Use the useBalances hook to retrieve the user's token balances. This hook automatically fetches balances when the wallet is connected.
import { useBalances } from '@megaeth-labs/wallet-sdk-react';
function BalancesList() {
// Get all tokens
const { data: allBalances, isLoading } = useBalances();
// Or get specific tokens
const { data: specificBalances } = useBalances(['0xTokenAddress1', '0xTokenAddress2']);
if (isLoading) return <div>Loading balances...</div>;
return (
<div>
{allBalances?.map(token => (
<div key={token.symbol}>
{token.symbol}: {token.displayBalance}
<span>USD Value: ${token.usdBalance}</span>
</div>
))}
</div>
);
}Open Wallet UI
Use the mega object to open the wallet interface for the user.
import { mega } from '@megaeth-labs/wallet-sdk-react';
function OpenWalletButton() {
return <button onClick={() => mega.open()}>Open Wallet</button>;
}Deposit Funds
Use the useDeposit hook to show the deposit UI to help users fund their wallet.
import { useDeposit } from '@megaeth-labs/wallet-sdk-react';
function DepositButton() {
const { mutate: deposit } = useDeposit();
return <button onClick={() => deposit()}>Deposit Funds</button>;
}Direct SDK Access
The React SDK exports the underlying mega object for direct access to all SDK methods when hooks are not suitable for your use case. This is useful for calling methods outside of React components or in event handlers.
import { mega } from '@megaeth-labs/wallet-sdk-react';
// Direct access to all SDK methods
await mega.connect();
await mega.disconnect();
await mega.transfer({ /* ... */ });
// ... all other SDK methods
// Event handling
mega.events.on('statusChange', ({ status, address }) => {
console.log('Status changed:', status, address);
});Note: When using MegaProvider, the SDK is automatically initialized, so you don't need to call mega.initialise() manually. The useStatus hook provides the initialization state via the initialised property.
