npm package: @keccak256-evg/passport-sdk
Description: T-REX Passport SDK for interacting with Passport and Registry contracts
Author: T-REX Team
Latest version: 1.2.0

# T-REX Passport SDK

[![npm version](https://badge.fury.io/js/@keccak256-evg/passport-sdk.svg)](https://badge.fury.io/js/@keccak256-evg/passport-sdk)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)

T-REX Passport SDK 是一个功能强大的 TypeScript 开发工具包，用于与 T-REX Passport 系统交互。支持 Thirdweb 和 Viem 两种底层库，提供灵活的区块链交互方式。

## ✨ 特性

- 🔗 **三库支持** - 支持 Thirdweb、Viem 和统一的 EIP-1193 接口
- 🎣 **React Hook** - 官方 React Hook 支持，简化状态管理
- 🎯 **Passport 管理** - 创建、绑定、解绑 Passport 功能
- 🔐 **多钱包支持** - 支持多个钱包绑定到同一个 Passport
- 📝 **完全类型化** - 提供完整的 TypeScript 类型定义
- 🔧 **灵活配置** - 支持环境配置和自定义合约地址
- 🌐 **多网络支持** - 支持多种区块链网络
- 📱 **模块化设计** - 清晰的项目结构，易于扩展
- 🔄 **通用兼容** - 支持所有 EIP-1193 兼容的钱包和库

## 📦 安装

```bash
npm install @keccak256-evg/passport-sdk
# 或
yarn add @keccak256-evg/passport-sdk
# 或
pnpm add @keccak256-evg/passport-sdk
```

## 🚀 快速开始

### 方式 1: 使用 React Hook（最简单）

```typescript
import { useUnifiedPassportSDK, useWalletPassport } from '@keccak256-evg/passport-sdk';

function MyPassportComponent({ userAddress }) {
  // 1. 初始化 SDK
  const { sdk, isInitializing, error } = useUnifiedPassportSDK({
    chain: {
      id: 1962,
      name: 'T-Rex Testnet',
      rpcUrls: { default: { http: ['https://testnetrpc.trex.xyz'] } }
    },
    autoInitialize: true
  });

  // 2. 检查钱包 Passport 状态
  const { hasPassport, passportId, isLoading } = useWalletPassport({
    sdk,
    walletAddress: userAddress,
    autoCheck: true
  });

  if (isInitializing) return <div>初始化中...</div>;
  if (error) return <div>错误: {error.message}</div>;
  if (isLoading) return <div>检查中...</div>;

  return (
    <div>
      {hasPassport ? (
        <p>✅ 您有 Passport (ID: {passportId})</p>
      ) : (
        <button onClick={() => sdk?.createPassport()}>
          创建 Passport
        </button>
      )}
    </div>
  );
}
```

> 📖 **更多 Hook 用法**: 查看 [React Hooks 指南](./REACT_HOOKS_GUIDE.md)

### 方式 2: 使用统一 SDK（EIP-1193）

```typescript
import { UnifiedPassportSDK } from '@keccak256-evg/passport-sdk';

// 支持任何 EIP-1193 兼容的钱包（MetaMask、Coinbase、WalletConnect 等）
const sdk = new UnifiedPassportSDK({
  provider: window.ethereum, // 任何 EIP-1193 provider
  chain: {
    id: 1962,
    name: 'T-Rex Testnet',
    rpcUrls: { default: { http: ['https://testnetrpc.trex.xyz'] } }
  }
});

// 连接钱包并检查 Passport
const accounts = await sdk.connectWallet();
const result = await sdk.checkWalletHasPassport(accounts[0]);
```

> 📖 **更多统一 SDK 用法**: 查看 [统一 SDK 指南](./UNIFIED_SDK_GUIDE.md)

### 方式 3: 使用 Viem（推荐）

#### 基础配置

```typescript
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { 
  ViemPassportSDK, 
  createViemPassportSDK, 
  Environment, 
  tRexTestnet 
} from "@keccak256-evg/passport-sdk";

// 便利方式创建 SDK（推荐）
const sdk = createViemPassportSDK({
  rpcUrl: "https://testnetrpc.trex.xyz",
  env: Environment.DEV,
  // 可选：添加账户用于发送交易
  account: privateKeyToAccount("0xYOUR_PRIVATE_KEY")
});
```

#### 手动创建客户端

```typescript
// 创建 Public Client
const publicClient = createPublicClient({
  chain: tRexTestnet,
  transport: http("https://testnetrpc.trex.xyz")
});

// 创建 Wallet Client（用于发送交易）
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const walletClient = createWalletClient({
  account,
  chain: tRexTestnet,
  transport: http("https://testnetrpc.trex.xyz")
});

// 创建 SDK 实例
const sdk = new ViemPassportSDK({
  publicClient,
  walletClient,
  network: tRexTestnet,
  env: Environment.DEV,
});
```

### 方式 4: 使用 Thirdweb（保持兼容）

```typescript
import { PassportSDK } from "@keccak256-evg/passport-sdk";
import { defineChain } from 'thirdweb/chains';
import { createThirdwebClient } from 'thirdweb';

// 创建链配置
const tRexTestnet = defineChain({
  id: 1962,
  name: 'T-Rex Testnet',
  nativeCurrency: { decimals: 18, name: 'Ether', symbol: 'ETH' },
  rpc: 'https://testnetrpc.trex.xyz',
  testnet: true,
});

// 创建 thirdweb 客户端
const client = createThirdwebClient({
  clientId: 'your-client-id',
});

// 创建 SDK 实例
const sdk = new PassportSDK({
  chain: tRexTestnet,
  registryAddress: '0x1B326360Ec9E3cEF6129173D35b86a6803e5751F',
  client: client,
});
```

## 📖 基本用法

### 查询操作

```typescript
// 检查钱包是否有 Passport
const hasPassport = await sdk.checkWalletHasPassport("0xWalletAddress");

// 获取 Passport 信息
const passportInfo = await sdk.getPassportInfo("0xPassportAddress");

// 获取绑定的钱包列表
const boundWallets = await sdk.getBoundWallets("0xPassportAddress");
```

### 交易操作

Passport SDK 支持两种发送交易的方式：

#### 方式 1: 准备交易 + 外部发送（适合 React 应用）

```typescript
// 1. 准备交易
const createTransaction = await sdk.createPassport();

// 2. 使用 React Hook 或其他方式发送
const { mutateAsync: sendTransaction } = useSendTransaction();
const result = await sendTransaction(createTransaction.preparedTransaction);
```

#### 方式 2: 直接发送交易（新功能）

```typescript
// 需要在 SDK 初始化时配置 account
const sdk = new PassportSDK({
  chain: tRexTestnet,
  registryAddress: '0x1B326360Ec9E3cEF6129173D35b86a6803e5751F',
  client: client,
  account: account // 添加账户用于签名
});

// 直接发送交易
const result = await sdk.createPassport({ sendTransaction: true });
console.log('Transaction hash:', result.transactionHash);

// 或者在调用时传入账户
const result = await sdk.createPassport({ 
  sendTransaction: true,
  account: someAccount 
});
```

### 所有支持 sendTransaction 的方法

```typescript
// 创建 Passport
const result = await sdk.createPassport({ sendTransaction: true });

// 请求绑定钱包
const result = await sdk.requestBindWallet(passportAddress, walletAddress, { 
  sendTransaction: true 
});

// 接受绑定请求
const result = await sdk.acceptBindRequest(passportAddress, { sendTransaction: true });

// 拒绝绑定请求
const result = await sdk.rejectBindRequest(passportAddress, { sendTransaction: true });

// 取消绑定请求
const result = await sdk.cancelBindRequest(passportAddress, walletAddress, { 
  sendTransaction: true 
});

// 解绑钱包
const result = await sdk.unbindWallet(passportAddress, { sendTransaction: true });

// 升级 Passport
const result = await sdk.upgradeMyPassport({ sendTransaction: true });
```

### 连接钱包（浏览器环境）

```typescript
// 连接 MetaMask
async function connectWallet() {
  if (typeof window.ethereum !== 'undefined') {
    const accounts = await window.ethereum.request({
      method: 'eth_requestAccounts'
    });
    
    // 使用 Viem 创建 wallet client
    const walletClient = createWalletClient({
      chain: tRexTestnet,
      transport: window.ethereum,
    });

    // 动态设置 wallet client
    sdk.setWalletClient(walletClient);
    
    return accounts[0];
  }
  throw new Error('请安装 MetaMask');
}
```

## 🌐 支持的网络

| 网络 | Chain ID | RPC URL |
|------|----------|---------|
| T-Rex 测试网 | 1962 | https://testnetrpc.trex.xyz |

## 🔧 配置选项

### Viem SDK 配置

```typescript
interface ViemPassportSDKConfig {
  publicClient: PublicClient;        // Viem 公共客户端
  walletClient?: WalletClient;       // Viem 钱包客户端（可选）
  network: Chain;                    // 网络配置
  env: Environment;                  // 环境配置
  registryAddress?: Address;         // Registry 合约地址（可选）
  rpcUrl?: string;                   // RPC URL（可选）
}
```

### 环境配置

```typescript
enum Environment {
  DEV = "DEV",     // 开发环境
  BETA = "BETA",   // 测试环境  
  PROD = "PROD"    // 生产环境
}
```

## 📚 API 文档

### 主要方法

#### Registry 方法

| 方法 | 描述 | 参数 | 返回值 |
|------|------|------|-------|
| `createPassport` | 创建新的 Passport | - | `Promise<TransactionHash>` |
| `checkWalletHasPassport` | 检查钱包是否有 Passport | `walletAddress` | `Promise<WalletPassportResult>` |
| `getPassportInfo` | 获取 Passport 详细信息 | `passportAddress` | `Promise<PassportInfo>` |
| `predictPassportAddress` | 预测 Passport 地址 | `walletAddress` | `Promise<Address>` |
| `upgradeMyPassport` | 升级 Passport | - | `Promise<TransactionHash>` |

#### Passport 方法

| 方法 | 描述 | 参数 | 返回值 |
|------|------|------|-------|
| `requestBindWallet` | 请求绑定钱包 | `passportAddress, walletAddress` | `Promise<TransactionHash>` |
| `acceptBindRequest` | 接受绑定请求 | `passportAddress` | `Promise<TransactionHash>` |
| `rejectBindRequest` | 拒绝绑定请求 | `passportAddress` | `Promise<TransactionHash>` |
| `unbindWallet` | 解绑钱包 | `passportAddress` | `Promise<TransactionHash>` |
| `getPendingBindWallets` | 获取待处理绑定钱包列表 | `passportAddress, account` | `Promise<Address[]>` |

## 🔍 示例代码

查看 `examples/` 目录获取更多完整示例：

- [Viem 使用示例](examples/viem-usage.ts) - 新的 Viem 方式
- [Thirdweb 使用示例](examples/usage.ts) - 原有 Thirdweb 方式

## 🏗️ 项目结构

```
src/
├── abi/                        # ABI 定义文件
│   ├── index.ts               # 统一导出
│   ├── PassportRegistry.ts    # Registry 合约 ABI
│   └── Passport.ts           # Passport 合约 ABI
├── constants/                 # 常量定义
│   ├── index.ts              # 统一导出
│   ├── addresses.ts          # 合约地址
│   ├── chains.ts             # 链配置
│   └── environment.ts        # 环境配置
├── types/                     # 类型定义
│   ├── index.ts              # 统一导出
│   ├── common.ts             # 通用类型
│   ├── passport.ts           # Passport 相关类型
│   └── config.ts             # 配置类型
├── utils/                     # 工具函数
│   ├── index.ts              # 统一导出
│   ├── viem.ts               # Viem 相关工具
│   └── common.ts             # 通用工具
├── PassportSDK.ts            # 原有 Thirdweb SDK
├── ViemPassportSDK.ts        # 新的 Viem SDK
└── index.ts                  # 主入口文件
```

## 🔄 迁移指南

从 Thirdweb 迁移到 Viem：

```typescript
// 旧方式 (Thirdweb)
import { PassportSDK } from "@keccak256-evg/passport-sdk";

// 新方式 (Viem)
import { ViemPassportSDK, createViemPassportSDK } from "@keccak256-evg/passport-sdk";

// 使用便利函数
const sdk = createViemPassportSDK({
  rpcUrl: "https://testnetrpc.trex.xyz",
  env: Environment.DEV,
});
```

## 🧪 测试

```bash
# 运行测试
npm test

# 运行代码检查
npm run lint

# 构建项目
npm run build
```

## 📚 相关文档

- 🎣 **[React Hooks 指南](./REACT_HOOKS_GUIDE.md)** - 官方 React Hook 使用指南
- 🔄 **[统一 SDK 指南](./UNIFIED_SDK_GUIDE.md)** - EIP-1193 统一接口使用指南
- 📖 **[API 参考](./examples/)** - 完整的使用示例
- 🔗 **[Viem 使用示例](./examples/viem-usage.ts)** - Viem 集成示例
- 📱 **[React 使用示例](./examples/react-hooks-usage.tsx)** - React Hook 完整示例

## 🤝 贡献

欢迎提交 Pull Request 和 Issue 来帮助改进这个 SDK！

## 📄 许可证

本项目采用 MIT 许可证。

## 📞 支持

如果您有任何问题或需要帮助，请在 GitHub Issues 中提问。

---

**Happy coding! 🚀**