@keccak256-evg/passport-sdk
Version:
T-REX Passport SDK for interacting with Passport and Registry contracts
465 lines (388 loc) • 10.6 kB
Markdown
# 🎣 React Hooks 使用指南
T-REX Passport SDK 现在提供官方的 React Hook 支持,让您能够轻松地在 React 应用中集成 Passport 功能!
## ✨ 特性
- 🔄 **自动状态管理** - 自动处理加载状态、错误处理和数据更新
- 🔗 **智能重连** - 自动监听钱包和网络变化
- ⚡ **轮询支持** - 可配置的数据轮询更新
- 🎯 **类型安全** - 完整的 TypeScript 支持
- 🧹 **自动清理** - 组件卸载时自动清理资源
- 📦 **可选依赖** - React 是可选的,不会影响非 React 用户
## 📦 安装
```bash
# 安装主包
npm install @keccak256-evg/passport-sdk
# 如果使用 React Hook,还需要安装 React(如果还没有的话)
npm install react
```
## 🚀 快速开始
### 1. useUnifiedPassportSDK - 主要 SDK Hook
```typescript
import { useUnifiedPassportSDK } from '@keccak256-evg/passport-sdk';
function MyComponent() {
const {
sdk,
isInitializing,
error,
providerInfo
} = useUnifiedPassportSDK({
chain: {
id: 1962,
name: 'T-Rex Testnet',
rpcUrls: { default: { http: ['https://testnetrpc.trex.xyz'] } }
},
autoInitialize: true, // 自动初始化
userAddress: userWalletAddress // 监听用户地址变化
});
if (isInitializing) return <div>初始化中...</div>;
if (error) return <div>错误: {error.message}</div>;
if (!sdk) return <div>请连接钱包</div>;
return <div>SDK 已就绪!钱包类型: {providerInfo?.isMetaMask ? 'MetaMask' : '其他'}</div>;
}
```
### 2. useWalletPassport - 检查钱包 Passport
```typescript
import { useWalletPassport } from '@keccak256-evg/passport-sdk';
function PassportStatus({ sdk, userAddress }) {
const {
hasPassport,
passportId,
passportAddress,
isLoading,
error,
check
} = useWalletPassport({
sdk,
walletAddress: userAddress,
autoCheck: true,
pollingInterval: 30000 // 每30秒检查一次
});
if (isLoading) return <div>检查中...</div>;
if (error) return <div>错误: {error.message} <button onClick={check}>重试</button></div>;
return (
<div>
{hasPassport ? (
<div>
✅ 您有 Passport!
<p>ID: {passportId}</p>
<p>地址: {passportAddress}</p>
</div>
) : (
<div>❌ 您还没有 Passport</div>
)}
</div>
);
}
```
### 3. usePassportInfo - 获取 Passport 详细信息
```typescript
import { usePassportInfo } from '@keccak256-evg/passport-sdk';
function PassportDetails({ sdk, passportAddress }) {
const {
passportInfo,
isLoading,
error,
refresh
} = usePassportInfo({
sdk,
passportAddress,
autoFetch: true,
pollingInterval: 60000 // 每分钟更新一次
});
if (isLoading) return <div>加载中...</div>;
if (error) return <div>错误: {error.message} <button onClick={refresh}>重新加载</button></div>;
if (!passportInfo) return null;
return (
<div>
<h3>Passport 详细信息</h3>
<p>ID: {passportInfo.passportId}</p>
<p>地址: {passportInfo.passportAddress}</p>
<p>绑定钱包数量: {passportInfo.walletCount}</p>
<div>
<h4>绑定的钱包:</h4>
{passportInfo.boundWallets.map((wallet, index) => (
<p key={index}>{wallet}</p>
))}
</div>
<button onClick={refresh}>刷新</button>
</div>
);
}
```
## 🔧 Hook API 参考
### useUnifiedPassportSDK
**配置选项:**
```typescript
interface UseUnifiedPassportSDKConfig {
chain: {
id: number;
name: string;
rpcUrls: { default: { http: string[] } };
nativeCurrency?: { name: string; symbol: string; decimals: number };
blockExplorers?: { default: { name: string; url: string } };
};
env?: 'dev' | 'prod';
registryAddress?: string;
autoInitialize?: boolean; // 默认 true
userAddress?: string; // 用于监听地址变化
}
```
**返回值:**
```typescript
interface UseUnifiedPassportSDKReturn {
sdk: UnifiedPassportSDK | null;
isInitializing: boolean;
error: Error | null;
initialize: () => Promise<void>;
cleanup: () => void;
providerInfo: {
isMetaMask: boolean;
isCoinbaseWallet: boolean;
chainId?: string;
selectedAddress?: string;
} | null;
}
```
### useWalletPassport
**配置选项:**
```typescript
interface UseWalletPassportConfig {
sdk: UnifiedPassportSDK | null;
walletAddress?: Address;
autoCheck?: boolean; // 默认 true
pollingInterval?: number; // 0 表示不轮询
}
```
**返回值:**
```typescript
interface UseWalletPassportReturn {
walletPassport: WalletPassportResult | null;
isLoading: boolean;
error: Error | null;
check: () => Promise<void>;
clear: () => void;
// 便捷属性
hasPassport: boolean;
passportId?: number;
passportAddress?: Address;
}
```
### usePassportInfo
**配置选项:**
```typescript
interface UsePassportInfoConfig {
sdk: UnifiedPassportSDK | null;
passportAddress?: Address;
autoFetch?: boolean; // 默认 true
pollingInterval?: number; // 0 表示不轮询
}
```
**返回值:**
```typescript
interface UsePassportInfoReturn {
passportInfo: PassportInfo | null;
isLoading: boolean;
error: Error | null;
refresh: () => Promise<void>;
clear: () => void;
}
```
## 💡 最佳实践
### 1. 组合使用 Hooks
```typescript
function PassportDashboard({ userAddress }) {
// 1. 初始化 SDK
const { sdk, isInitializing, error } = useUnifiedPassportSDK({
chain: tRexTestnetConfig,
userAddress,
autoInitialize: true
});
// 2. 检查钱包状态
const { hasPassport, passportAddress } = useWalletPassport({
sdk,
walletAddress: userAddress,
autoCheck: true
});
// 3. 获取详细信息(仅当有 Passport 时)
const { passportInfo } = usePassportInfo({
sdk,
passportAddress: hasPassport ? passportAddress : undefined,
autoFetch: true
});
// 渲染逻辑...
}
```
### 2. 自定义 Hook
```typescript
// 封装常用逻辑
function usePassportOperations(userAddress?: string) {
const sdkResult = useUnifiedPassportSDK({
chain: tRexTestnetConfig,
userAddress,
autoInitialize: true
});
const walletResult = useWalletPassport({
sdk: sdkResult.sdk,
walletAddress: userAddress,
autoCheck: true
});
const createPassport = async () => {
if (!sdkResult.sdk) throw new Error('SDK not ready');
return await sdkResult.sdk.createPassport();
};
return {
...sdkResult,
...walletResult,
createPassport,
isReady: !!sdkResult.sdk && !sdkResult.isInitializing && !sdkResult.error
};
}
// 使用自定义 Hook
function MyComponent({ userAddress }) {
const {
isReady,
hasPassport,
createPassport,
isInitializing
} = usePassportOperations(userAddress);
if (isInitializing) return <div>加载中...</div>;
if (!isReady) return <div>SDK 未就绪</div>;
return (
<div>
{hasPassport ? (
<div>您已有 Passport</div>
) : (
<button onClick={createPassport}>创建 Passport</button>
)}
</div>
);
}
```
### 3. 错误处理
```typescript
function ErrorBoundaryComponent() {
const { sdk, error, initialize } = useUnifiedPassportSDK({
chain: tRexTestnetConfig,
autoInitialize: true
});
// 全局错误处理
React.useEffect(() => {
if (error) {
console.error('SDK Error:', error);
// 可以发送到错误追踪服务
// trackError(error);
}
}, [error]);
if (error) {
return (
<div className="error-state">
<h3>出错了 😞</h3>
<p>{error.message}</p>
<button onClick={initialize}>重试</button>
<details>
<summary>技术详情</summary>
<pre>{error.stack}</pre>
</details>
</div>
);
}
// 正常渲染...
}
```
### 4. 轮询控制
```typescript
function PassportMonitor({ userAddress }) {
const [isMonitoring, setIsMonitoring] = useState(true);
const { hasPassport, passportAddress } = useWalletPassport({
sdk,
walletAddress: userAddress,
autoCheck: true,
pollingInterval: isMonitoring ? 30000 : 0 // 根据状态控制轮询
});
return (
<div>
<label>
<input
type="checkbox"
checked={isMonitoring}
onChange={e => setIsMonitoring(e.target.checked)}
/>
启用自动监控
</label>
{/* 其他内容... */}
</div>
);
}
```
## 🎨 样式建议
```css
/* 推荐的基础样式 */
.passport-dashboard {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.passport-dashboard.loading {
text-align: center;
opacity: 0.7;
}
.passport-dashboard.error {
border: 2px solid #ff6b6b;
border-radius: 8px;
padding: 20px;
background: #ffe0e0;
}
.provider-info {
background: #f0f8ff;
padding: 15px;
border-radius: 8px;
margin: 15px 0;
}
.wallet-passport {
border: 1px solid #ddd;
padding: 15px;
border-radius: 8px;
margin: 15px 0;
}
.has-passport {
color: #4caf50;
}
.no-passport {
color: #ff9800;
}
.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}
.actions button {
padding: 10px 15px;
border: none;
border-radius: 5px;
background: #007bff;
color: white;
cursor: pointer;
}
.actions button:hover {
background: #0056b3;
}
```
## 📱 完整示例
查看 [`examples/react-hooks-usage.tsx`](./examples/react-hooks-usage.tsx) 获取完整的使用示例,包括:
- 完整的 Passport 仪表板
- 错误处理和重试逻辑
- 自定义 Hook 封装
- 轮询和实时更新
- 样式和用户体验最佳实践
## ❓ 常见问题
### Q: Hook 是否支持服务端渲染 (SSR)?
A: 部分支持。Hook 会自动检测环境,在服务端不会尝试访问 `window` 对象,但 SDK 功能需要在客户端才能工作。
### Q: 如何处理网络切换?
A: Hook 会自动监听网络变化并在控制台输出警告。您可以通过 `providerInfo.chainId` 检查当前网络。
### Q: 是否可以同时使用多个 SDK 实例?
A: 可以,每个 Hook 实例都是独立的。但通常一个应用只需要一个 SDK 实例。
### Q: Hook 的性能如何?
A: Hook 使用了 React 的最佳实践,包括 `useCallback`、`useMemo` 等优化。轮询是可选的,不会影响不需要实时数据的组件。
### Q: 如何在 React Native 中使用?
A: 目前主要针对 Web 环境优化。React Native 支持可能需要额外的 polyfill 和配置。
---
**开始使用 React Hook 让 Passport 集成变得前所未有的简单!** 🚀