@w3art/profile-manager
v2.0.2
Published
Chrome user data directory manager for EOA-specific persistent profiles
Readme
@web3/profile-manager
🎯 Chrome 用户目录准备器 v2.0
为 EOA 地址准备持久化的 Chrome userDataDir,实现浏览器身份长期有状态管理。
✨ 核心功能
- ✅ 自动分片目录管理:
{base}/{前2位}/{中2位}/{后36位} - ✅ 母版模板复制:新兵首次使用时从
{templateBase}/{walletPin}复制初始化 - ✅ 老兵直接复用:已存在的目录直接使用,保留历史状态
- ✅ 多磁盘智能选择:按优先级自动选择可用的存储卷
- ✅ 完全类型安全:TypeScript 严格模式,零
any
📦 安装
pnpm add @web3/profile-manager🚀 快速开始
基础用法
import { prepareUserDataDir } from '@web3/profile-manager';
// 设置环境变量
process.env.EOA_ADDRESS = '0xabcdef1234567890abcdef1234567890abcdef12';
process.env.WALLET_PIN_ID = '41';
// 准备用户目录
const result = await prepareUserDataDir();
console.log(result.userDataDir);
// 输出: /M4-4t/ab/cd/ef1234567890abcdef1234567890abcdef12
console.log(result.initialized);
// 输出: true (新兵) 或 false (老兵)在 Playwright Runner 中使用
import { chromium } from 'playwright';
import { prepareUserDataDir, DEFAULT_CHROME_LAUNCH_ARGS } from '@web3/profile-manager';
// 准备用户目录
const { userDataDir, initialized } = await prepareUserDataDir();
if (initialized) {
console.log('🎖️ 新兵首次初始化完成');
} else {
console.log('♻️ 老兵复用现有目录');
}
// 启动 Chrome
const context = await chromium.launchPersistentContext(userDataDir, {
headless: false,
args: DEFAULT_CHROME_LAUNCH_ARGS,
});🔧 环境变量配置
必需环境变量
| 变量 | 说明 | 示例 |
| --------------- | ---------------------- | ------------- |
| EOA_ADDRESS | EOA 地址(0x开头40位) | 0xabcdef... |
| WALLET_PIN_ID | 钱包模板编号 | 41 |
可选环境变量
| 变量 | 说明 | 默认值 |
| ------------------------------- | -------------------------- | ------------------------------------------------------------------------------------- |
| PROFILES_SEARCH_PATHS | 用户数据卷路径(逗号分隔) | /M4-4t,/sandiskpro-4t,/UDISK_15G |
| MASTER_TEMPLATES_SEARCH_PATHS | 母版模板路径(逗号分隔) | /master_templates_m4-4t,/master_templates_sandiskpro-4t,/master_templates_udisk-15g |
📂 目录结构
用户数据目录(分片存储)
/M4-4t/
├── ab/ # 前2位
│ ├── cd/ # 中2位
│ │ └── ef12...34/ # 后36位(完整 userDataDir)
│ │ ├── Default/
│ │ ├── Extensions/
│ │ └── ...母版模板目录(按 walletPin)
/master_templates_m4-4t/
├── 41/ # walletPin=41 的模板
│ ├── Default/
│ ├── Extensions/
│ └── ...
├── 42/ # walletPin=42 的模板
└── ...🎨 导出的常量
import {
CHROME_VERSION, // '140.0.7339.185' (与 .versions.env 保持一致)
CHROME_EXECUTABLE_PATH, // '/usr/bin/google-chrome'
DEFAULT_CHROME_LAUNCH_ARGS, // Chrome 启动参数数组
DEFAULT_PROFILES_SEARCH_PATHS, // ['/M4-4t', '/sandiskpro-4t', '/UDISK_15G']
DEFAULT_TEMPLATES_SEARCH_PATHS, // ['/master_templates_m4-4t', ...]
SKIP_COPY_PATTERNS, // 跳过复制的目录正则
} from '@web3/profile-manager';📋 API 参考
prepareUserDataDir()
准备 Chrome 用户数据目录。
返回:Promise<PrepareResult>
interface PrepareResult {
userDataDir: string; // 目标目录路径
initialized: boolean; // 是否为本次初始化
templateSource?: string; // 使用的模板路径(仅初始化时)
}异常:
Error('EOA_ADDRESS is required')- 缺少 EOA 地址Error('WALLET_PIN_ID is required')- 缺少钱包编号Error('Invalid EOA address format')- EOA 格式错误Error('No accessible profiles base path')- 无可用存储卷Error('Master template not found')- 母版模板不存在
🔍 工具函数
normalizeEoaAddress(eoa: string): string
标准化 EOA 地址为 40 位小写十六进制(去除 0x 前缀)。
import { normalizeEoaAddress } from '@web3/profile-manager';
normalizeEoaAddress('0xAbCd...');
// 返回: 'abcd...'buildShardedUserPath(base: string, normalizedHex40: string): string
构建分片路径。
import { buildShardedUserPath } from '@web3/profile-manager';
buildShardedUserPath('/M4-4t', 'abcdef1234567890...');
// 返回: '/M4-4t/ab/cd/ef1234567890...'findFirstExistingBasePath(paths: string[], description: string): Promise<string>
查找第一个存在的路径。
getEnvList(envKey: string, fallbackCommaList: string): string[]
从环境变量读取逗号分隔的路径列表。
🎯 设计原则
1. 极致的身份隔离
每个 EOA 拥有独立的 userDataDir,完全隔离 Cookies、LocalStorage、扩展状态等。
2. 长期有状态管理
"老兵"复用现有目录,保留完整的浏览器历史和身份状态。
3. 防女巫优化
- 固定 Chrome 版本(
140.0.7339.185,与 Playwright Runner Docker 一致) - 唯一指纹绑定
- 持久化身份特征
4. 性能优化
- 跳过缓存目录复制(
Cache、GPUCache等) - 分片存储避免单目录文件过多
- 多磁盘智能负载均衡
📊 包信息
- 版本:2.0.0
- 文件数:3 个源文件
- 代码量:~330 行
- 依赖:仅 Node.js 内置模块
- 构建产物:ESM + TypeScript 声明文件
🔄 从 v1.0 迁移
v2.0 大幅简化,删除了冗余的 OOP 包装层:
// ❌ v1.0 (已废弃)
import { ProfileManager } from '@web3/profile-manager';
const manager = ProfileManager.getInstance();
await manager.createWorkspace(eoaAddress);
// ✅ v2.0 (推荐)
import { prepareUserDataDir } from '@web3/profile-manager';
const result = await prepareUserDataDir();📄 许可证
MIT
🤝 贡献
欢迎提交 Issue 和 Pull Request!
