Web3 Wallet Integration โ
HaloLight Web3 provides unified access to EVM + Solana + IPFS, with Core/React/Vue packages.
GitHub: https://github.com/halolight/halolight-web3
npm:
@halolight/web3-core- Core functionality (framework-agnostic)@halolight/web3-react- React components and hooks@halolight/web3-vue- Vue 3 components and composables
Tech Stack โ
| Technology | Version | Description |
|---|---|---|
| wagmi | ^2.12.x | EVM wallet and contract calls |
| viem | ^2.21.x | EVM RPC & ABI utilities |
| @solana/web3.js | ^1.95.x | Solana JavaScript SDK |
| @solana/wallet-adapter | latest | Solana wallet adapters |
| @web3-storage/w3up-client | ^16.0.x | IPFS/web3.storage client |
| siwe | ^2.3.x | Sign-In with Ethereum |
| TypeScript | ^5.7.x | Type system |
| Turborepo | ^2.3.x | Monorepo build tool |
Core Features โ
EVM (Ethereum/Polygon/BSC) โ
- Wallet connection (MetaMask, WalletConnect, etc.)
- Sign-In with Ethereum (SIWE)
- ERC-20 token interactions
- ERC-721 NFT support
- Smart contract calls (read/write)
- Gas estimation & management
- Multi-chain support
Solana โ
- Wallet adapter integration (Phantom, Solflare, etc.)
- Signature-based authentication
- SOL transfers
- SPL Token support
- Transaction management
- Devnet/Testnet/Mainnet support
IPFS โ
- File upload (web3.storage)
- JSON metadata upload
- NFT metadata handling
- CID validation & conversion
- Gateway URL management
- Batch upload with progress
Directory Structure โ
halolight-web3/
โโโ packages/
โ โโโ core/ # Core package (@halolight/web3-core)
โ โ โโโ src/
โ โ โ โโโ evm/ # EVM/Ethereum functionality
โ โ โ โ โโโ wallet.ts # Wagmi configuration
โ โ โ โ โโโ chains.ts # Chain configuration
โ โ โ โ โโโ siwe.ts # Sign-In with Ethereum
โ โ โ โ โโโ contracts.ts # Smart contract interaction
โ โ โ โโโ solana/ # Solana functionality
โ โ โ โ โโโ wallet.ts # Wallet adapters
โ โ โ โ โโโ auth.ts # Signature authentication
โ โ โ โโโ storage/ # Storage functionality
โ โ โ โ โโโ ipfs.ts # IPFS upload
โ โ โ โโโ types/ # TypeScript types
โ โ โ โโโ utils/ # Utilities
โ โ โโโ package.json
โ โ
โ โโโ react/ # React package (@halolight/web3-react)
โ โ โโโ src/
โ โ โ โโโ providers/
โ โ โ โ โโโ Web3Provider.tsx
โ โ โ โโโ components/
โ โ โ โ โโโ WalletButton.tsx
โ โ โ โ โโโ TokenBalance.tsx
โ โ โ โ โโโ NftGallery.tsx
โ โ โ โ โโโ ContractCall.tsx
โ โ โ โโโ hooks/
โ โ โโโ package.json
โ โ
โ โโโ vue/ # Vue package (@halolight/web3-vue)
โ โโโ src/
โ โ โโโ composables/
โ โ โ โโโ useWallet.ts
โ โ โโโ components/
โ โ โโโ WalletButton.vue
โ โ โโโ TokenBalance.vue
โ โโโ package.json
โ
โโโ .env.example
โโโ turbo.json
โโโ pnpm-workspace.yaml
โโโ package.jsonQuick Start โ
Installation โ
bash
# Using pnpm (recommended)
pnpm add @halolight/web3-core @halolight/web3-react
# or for Vue
pnpm add @halolight/web3-core @halolight/web3-vue
# Using npm
npm install @halolight/web3-core @halolight/web3-react
# Using yarn
yarn add @halolight/web3-core @halolight/web3-reactEnvironment Variables โ
Copy .env.example to .env and configure:
env
# EVM - RPC nodes
NEXT_PUBLIC_ALCHEMY_API_KEY=your_alchemy_key
NEXT_PUBLIC_INFURA_API_KEY=your_infura_key
# EVM - WalletConnect
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=your_project_id
# Solana
NEXT_PUBLIC_SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
# IPFS/web3.storage
NEXT_PUBLIC_WEB3_STORAGE_TOKEN=your_web3_storage_tokenReact Example โ
tsx
import { Web3Provider, WalletButton, TokenBalance } from '@halolight/web3-react';
function App() {
return (
<Web3Provider
evmNetwork="mainnet"
solanaCluster="mainnet-beta"
enableEvm={true}
enableSolana={true}
>
<div>
<WalletButton chain="evm" />
<WalletButton chain="solana" />
<TokenBalance
chain="evm"
tokenAddress="0x..." // USDC on Ethereum
showSymbol
/>
</div>
</Web3Provider>
);
}Vue Example โ
vue
<script setup lang="ts">
import { WalletButton, TokenBalance, useEvmWallet } from '@halolight/web3-vue';
import { WagmiPlugin } from '@wagmi/vue';
import { createWagmiConfig } from '@halolight/web3-core';
const config = createWagmiConfig('mainnet');
</script>
<template>
<div>
<WalletButton />
<TokenBalance
token-address="0x..."
:show-symbol="true"
/>
</div>
</template>Core Library (Framework-agnostic) โ
typescript
import {
createWagmiConfig,
getTokenBalance,
uploadToIpfs,
authenticateWithSiwe,
} from '@halolight/web3-core';
// EVM: Get token balance
const balance = await getTokenBalance(client, tokenAddress, walletAddress);
// IPFS: Upload file
const result = await uploadToIpfs(file);
console.log(result.cid, result.gateway);
// SIWE: Authenticate user
const auth = await authenticateWithSiwe({
domain: 'example.com',
address: walletAddress,
chainId: 1,
signMessage: async (msg) => wallet.signMessage(msg),
});React Components โ
Web3Provider โ
Unified EVM + Solana Provider:
tsx
<Web3Provider
evmNetwork="mainnet" // or "testnet" | "development"
solanaCluster="mainnet-beta" // or "devnet" | "testnet"
enableEvm={true} // Enable EVM support
enableSolana={true} // Enable Solana support
>
{children}
</Web3Provider>WalletButton โ
tsx
import { WalletButton, DefaultWalletButton } from '@halolight/web3-react';
// EVM wallet
<WalletButton
chain="evm"
connectText="Connect Ethereum"
className="custom-class"
/>
// Solana wallet
<WalletButton
chain="solana"
className="custom-class"
/>
// With default styling
<DefaultWalletButton chain="evm" />TokenBalance โ
tsx
import { TokenBalance } from '@halolight/web3-react';
<TokenBalance
chain="evm"
tokenAddress="0x..." // ERC-20 contract address
showSymbol
decimals={4}
loadingComponent={<Spinner />}
errorComponent={(error) => <div>Error: {error}</div>}
/>NftGallery โ
tsx
import { NftGallery } from '@halolight/web3-react';
<NftGallery
contractAddress="0x..." // ERC-721 contract
maxDisplay={50}
columns={3}
renderNft={(nft) => (
<div>
<img src={nft.image} alt={nft.name} />
<h3>{nft.name}</h3>
</div>
)}
/>ContractCall โ
tsx
import { ContractCallButton, useContractCall } from '@halolight/web3-react';
// Using component
<ContractCallButton
contract={{
address: '0x...',
abi: MyABI,
functionName: 'mint',
args: [tokenId],
}}
type="write"
buttonText="Mint NFT"
onSuccess={(data) => console.log('Minted!', data)}
/>
// Using hook
const { call, loading, error, txHash } = useContractCall(
{
address: '0x...',
abi: MyABI,
functionName: 'balanceOf',
args: [address],
},
'read'
);Vue Composables โ
useEvmWallet โ
typescript
import { useEvmWallet } from '@halolight/web3-vue';
const { address, isConnected, connect, disconnect } = useEvmWallet();useTokenBalance โ
typescript
import { useTokenBalance } from '@halolight/web3-vue';
const { balance, loading, error, refresh } = useTokenBalance('0x...');useNativeBalance โ
typescript
import { useNativeBalance } from '@halolight/web3-vue';
const { balance, formatted, loading } = useNativeBalance();Core API โ
EVM Wallet โ
typescript
import {
createWagmiConfig,
formatAddress,
isValidAddress,
} from '@halolight/web3-core';
// Create wagmi configuration
const config = createWagmiConfig('mainnet');
// Format address
const short = formatAddress('0x1234...5678'); // "0x1234...5678"
// Validate address
const valid = isValidAddress('0x...'); // true/falseSmart Contracts โ
typescript
import {
readContract,
writeContract,
getTokenBalance,
transferToken,
ERC20_ABI,
} from '@halolight/web3-core';
// Read contract
const name = await readContract(publicClient, {
address: '0x...',
abi: ERC20_ABI,
functionName: 'name',
});
// Write contract
const hash = await writeContract(walletClient, publicClient, {
address: '0x...',
abi: ERC20_ABI,
functionName: 'transfer',
args: [toAddress, amount],
});SIWE Authentication โ
typescript
import {
createSiweMessage,
formatSiweMessage,
verifySiweMessage,
authenticateWithSiwe,
} from '@halolight/web3-core';
// Complete authentication flow
const result = await authenticateWithSiwe({
domain: 'example.com',
address: walletAddress,
chainId: 1,
signMessage: async (message) => {
return await wallet.signMessage(message);
},
});
if (result.success) {
console.log('Authenticated:', result.address);
}Solana Wallet โ
typescript
import {
createSolanaConnection,
getSolBalance,
transferSol,
} from '@halolight/web3-core';
// Create connection
const connection = createSolanaConnection('mainnet-beta');
// Get SOL balance
const balance = await getSolBalance(connection, walletAddress);
// Transfer SOL
const signature = await transferSol(
connection,
wallet,
toAddress,
1.0 // 1 SOL
);IPFS Storage โ
typescript
import {
uploadToIpfs,
uploadJsonToIpfs,
fetchJsonFromIpfs,
ipfsToHttp,
} from '@halolight/web3-core';
// Upload file
const result = await uploadToIpfs(file);
console.log(result.cid); // "QmXxx..."
console.log(result.gateway); // "https://w3s.link/ipfs/QmXxx..."
// Upload JSON
const metadata = await uploadJsonToIpfs({
name: 'My NFT',
description: 'Cool NFT',
image: 'ipfs://QmYyy...',
});
// Fetch JSON
const data = await fetchJsonFromIpfs('QmXxx...');
// Convert IPFS URL to HTTP
const url = ipfsToHttp('ipfs://QmXxx...'); // "https://w3s.link/ipfs/QmXxx..."Development Guide โ
Common Commands โ
bash
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Development mode (watch)
pnpm dev
# Run tests
pnpm test
# Type check
pnpm type-check
# Lint
pnpm lint
# Clean build artifacts
pnpm cleanSingle Package Operations โ
bash
# In packages/core directory
pnpm build
pnpm dev
pnpm test
# Or from root
pnpm --filter @halolight/web3-core build
pnpm --filter @halolight/web3-react devBest Practices โ
RPC Configuration โ
- Configure RPC keys properly (Alchemy/Infura) to avoid rate limiting
- Use RPC fallback mechanism for better availability
Error Handling โ
- Handle on-chain errors and rejection states
- Provide clear UI feedback
Security โ
- Never expose private keys/sensitive tokens in production
- Use backend signing and proxy forwarding
- Validate all user inputs
Related Projects โ
- halolight - Next.js frontend
- halolight-vue - Vue frontend
- halolight-docs - Documentation