--- name: walrus-code-generator description: 自动生成 Walrus TypeScript SDK 集成代码和最佳实践模板 parameters: - name: use-case type: string description: 使用场景 (basic-upload/advanced-storage/browser-app/batch-processing) required: true - name: framework type: string description: 开发框架 (react/vue/nodejs/nextjs/express) default: nodejs - name: features type: array description: 需要的功能特性 default: [] - name: environment type: string description: 部署环境 (development/production) default: development --- # Walrus 代码生成技能 ## 技能概述 `walrus-code-generator` 是一个专业的代码生成助手,根据您的具体需求自动生成 Walrus TypeScript SDK 集成代码。支持多种使用场景、开发框架和部署环境,确保生成的代码符合最佳实践。 ## 支持的使用场景 ### 1. 基础文件上传 (basic-upload) ```typescript // 自动生成的基础上传服务 skill: "walrus-code-generator" // use-case: basic-upload // framework: nodejs // features: ["error-handling", "progress-tracking"] export class BasicWalrusUploader { private client: any; private signer: any; constructor(network: 'testnet' | 'mainnet' = 'testnet') { const suiClient = new SuiJsonRpcClient({ url: getFullnodeUrl(network), network, }).$extend(walrus()); this.client = suiClient; this.signer = this.createSigner(); } async uploadFile( filePath: string, options: UploadOptions = {} ): Promise { const { epochs = 10, deletable = true, tags = {}, onProgress = () => {} } = options; try { onProgress(25, '读取文件...'); const fs = await import('fs/promises'); const fileContent = await fs.readFile(filePath); const fileName = filePath.split('/').pop() || 'unknown'; onProgress(50, '创建 Walrus 文件...'); const file = WalrusFile.from({ contents: fileContent, identifier: `uploads/${Date.now()}_${fileName}`, mimeType: this.getMimeType(filePath), attributes: { 'original-path': filePath, 'file-size': fileContent.length.toString(), 'upload-time': new Date().toISOString(), ...tags } }); onProgress(75, '上传到网络...'); const result = await this.client.walrus.writeFiles({ files: [file], epochs, deletable, signer: this.signer }); onProgress(100, '上传完成'); return { success: true, blobId: result[0].blobId, fileName, size: fileContent.length, storedUntil: result[0].storedUntil }; } catch (error) { console.error('上传失败:', error.message); throw new Error(`上传失败: ${error.message}`); } } private createSigner(): Ed25519Keypair { const privateKey = process.env.WALRUS_PRIVATE_KEY; if (!privateKey) { throw new Error('未找到私钥环境变量 WALRUS_PRIVATE_KEY'); } return Ed25519Keypair.fromSecretKey(privateKey); } private getMimeType(filePath: string): string { const ext = filePath.split('.').pop()?.toLowerCase(); const mimeTypes: Record = { 'txt': 'text/plain', 'pdf': 'application/pdf', 'jpg': 'image/jpeg', 'png': 'image/png', 'json': 'application/json' }; return mimeTypes[ext || ''] || 'application/octet-stream'; } } interface UploadOptions { epochs?: number; deletable?: boolean; tags?: Record; onProgress?: (progress: number, message: string) => void; } interface UploadResult { success: boolean; blobId: string; fileName: string; size: number; storedUntil: Date; } ``` ### 2. 高级存储管理 (advanced-storage) ```typescript // 自动生成的高级存储管理服务 skill: "walrus-code-generator" // use-case: advanced-storage // framework: nodejs // features: ["batch-operations", "retry-logic", "cache-management", "metadata-indexing"] export class AdvancedWalrusStorage { private client: any; private signer: any; private cache: Map = new Map(); private retryConfig: RetryConfig; constructor(options: AdvancedStorageOptions = {}) { const { network = 'testnet', retryAttempts = 3, retryDelay = 1000, cacheEnabled = true, cacheTTL = 300000 // 5分钟 } = options; const suiClient = new SuiJsonRpcClient({ url: getFullnodeUrl(network), network, }).$extend(walrus({ storageNodeClientOptions: { timeout: 60000, onError: (error) => console.warn('存储节点错误:', error) } })); this.client = suiClient; this.signer = this.createSigner(); this.retryConfig = { attempts: retryAttempts, delay: retryDelay }; this.cacheEnabled = cacheEnabled; this.cacheTTL = cacheTTL; } async batchUpload( files: FileUploadRequest[], options: BatchUploadOptions = {} ): Promise { const { epochs = 10, deletable = true, maxConcurrency = 3, commonTags = {} } = options; const results: UploadResult[] = []; const errors: UploadError[] = []; // 分批处理 for (let i = 0; i < files.length; i += maxConcurrency) { const batch = files.slice(i, i + maxConcurrency); const batchPromises = batch.map(async (fileRequest, index) => { try { const result = await this.uploadWithRetry(fileRequest, { epochs, deletable, tags: { ...commonTags, ...fileRequest.tags } }); results.push({ ...result, originalPath: fileRequest.path, batchIndex: i + index }); } catch (error) { errors.push({ originalPath: fileRequest.path, error: error.message, batchIndex: i + index }); } }); await Promise.all(batchPromises); // 批次间延迟 if (i + maxConcurrency < files.length) { await new Promise(resolve => setTimeout(resolve, 500)); } } return { totalFiles: files.length, successful: results.length, failed: errors.length, results, errors }; } async smartDownload( blobId: string, options: SmartDownloadOptions = {} ): Promise { const { forceRefresh = false, verifyIntegrity = true, cacheKey = blobId } = options; // 检查缓存 if (!forceRefresh && this.cacheEnabled) { const cached = this.getFromCache(cacheKey); if (cached) { console.log('从缓存返回文件:', blobId); return { ...cached, fromCache: true }; } } try { const result = await this.downloadWithVerification(blobId, verifyIntegrity); // 缓存结果 if (this.cacheEnabled) { this.setToCache(cacheKey, result); } return { ...result, fromCache: false }; } catch (error) { throw new Error(`智能下载失败: ${error.message}`); } } async searchByTags(tags: Record): Promise { // 这是一个概念性实现 // 实际搜索需要基于您自己的元数据索引系统 const indexedFiles = await this.getIndexedFiles(); return indexedFiles.filter(file => { return Object.entries(tags).every(([key, value]) => file.tags[key] === value ); }); } private async uploadWithRetry( fileRequest: FileUploadRequest, options: UploadOptions ): Promise { const { attempts, delay } = this.retryConfig; for (let attempt = 1; attempt <= attempts; attempt++) { try { return await this.uploadSingleFile(fileRequest, options); } catch (error) { if (attempt < attempts && this.isRetryableError(error)) { console.log(`上传失败,第 ${attempt} 次重试...`); await new Promise(resolve => setTimeout(resolve, delay * attempt)); continue; } throw error; } } throw new Error('上传失败,已达到最大重试次数'); } private async uploadSingleFile( fileRequest: FileUploadRequest, options: UploadOptions ): Promise { const fs = await import('fs/promises'); const fileContent = await fs.readFile(fileRequest.path); const file = WalrusFile.from({ contents: fileContent, identifier: fileRequest.identifier || `files/${Date.now()}_${fileRequest.path}`, mimeType: fileRequest.mimeType || this.getMimeType(fileRequest.path), attributes: { 'original-path': fileRequest.path, 'file-size': fileContent.length.toString(), 'upload-time': new Date().toISOString(), ...options.tags } }); const result = await this.client.walrus.writeFiles({ files: [file], epochs: options.epochs, deletable: options.deletable, signer: this.signer }); // 索引文件元数据 await this.indexFile({ blobId: result[0].blobId, identifier: file.identifier, path: fileRequest.path, size: fileContent.length, tags: options.tags, uploadTime: new Date() }); return { success: true, blobId: result[0].blobId, identifier: file.identifier, size: fileContent.length, storedUntil: result[0].storedUntil }; } private async downloadWithVerification( blobId: string, verify: boolean ): Promise { const [file] = await this.client.walrus.getFiles({ ids: [blobId] }); const exists = await file.exists(); if (!exists) { throw new Error(`文件不存在: ${blobId}`); } const content = await file.bytes(); let verified = true; if (verify) { const verification = await this.verifyFileIntegrity(blobId, content); verified = verification.valid; } return { blobId, content: Buffer.from(content), size: content.length, storedUntil: await file.storedUntil(), verified, metadata: await this.getFileMetadata(file) }; } private async verifyFileIntegrity( blobId: string, content: Uint8Array ): Promise<{ valid: boolean; error?: string }> { try { // 基本完整性检查 if (content.length === 0) { return { valid: false, error: '文件内容为空' }; } // 这里可以添加更复杂的验证逻辑 return { valid: true }; } catch (error) { return { valid: false, error: error.message }; } } // 缓存管理 private getFromCache(key: string): CachedFile | null { const cached = this.cache.get(key); if (cached && Date.now() - cached.timestamp < this.cacheTTL) { return cached; } this.cache.delete(key); return null; } private setToCache(key: string, file: SmartDownloadResult): void { this.cache.set(key, { ...file, timestamp: Date.now() }); } private isRetryableError(error: any): boolean { return error instanceof RetryableWalrusClientError || error.message.includes('timeout') || error.message.includes('network'); } } // 类型定义 interface FileUploadRequest { path: string; identifier?: string; mimeType?: string; tags?: Record; } interface BatchUploadOptions { epochs?: number; deletable?: boolean; maxConcurrency?: number; commonTags?: Record; } interface BatchUploadResult { totalFiles: number; successful: number; failed: number; results: (UploadResult & { originalPath: string; batchIndex: number })[]; errors: UploadError[]; } interface SmartDownloadOptions { forceRefresh?: boolean; verifyIntegrity?: boolean; cacheKey?: string; } interface SmartDownloadResult { blobId: string; content: Buffer; size: number; storedUntil: Date; verified: boolean; metadata: any; fromCache: boolean; } interface CachedFile extends SmartDownloadResult { timestamp: number; } interface RetryConfig { attempts: number; delay: number; } ``` ### 3. React 浏览器应用 (browser-app) ```typescript // 自动生成的 React Hook 和组件 skill: "walrus-code-generator" // use-case: browser-app // framework: react // features: ["wallet-integration", "progress-tracking", "drag-drop"] import React, { useState, useCallback, createContext, useContext } from 'react'; import { useWallet } from '@suiet/wallet-kit'; // Walrus Context const WalrusContext = createContext<{ upload: (files: FileList) => Promise; download: (blobId: string, filename?: string) => Promise; isUploading: boolean; } | null>(null); export const WalrusProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const { connected, signAndExecuteTransactionBlock } = useWallet(); const [isUploading, setIsUploading] = useState(false); const upload = useCallback(async (files: FileList): Promise => { if (!connected) { throw new Error('请先连接钱包'); } setIsUploading(true); const results: UploadResult[] = []; try { for (let i = 0; i < files.length; i++) { const file = files[i]; try { const result = await uploadFile(file, signAndExecuteTransactionBlock); results.push({ ...result, originalName: file.name, index: i }); } catch (error) { results.push({ success: false, originalName: file.name, index: i, error: error.message }); } } } finally { setIsUploading(false); } return results; }, [connected, signAndExecuteTransactionBlock]); const download = useCallback(async (blobId: string, filename?: string) => { await downloadFile(blobId, filename); }, []); return ( {children} ); }; export const useWalrus = () => { const context = useContext(WalrusContext); if (!context) { throw new Error('useWalrus must be used within WalrusProvider'); } return context; }; // 文件上传组件 export const WalrusUpload: React.FC<{ onUploadComplete?: (results: UploadResult[]) => void; maxFiles?: number; acceptedTypes?: string; }> = ({ onUploadComplete, maxFiles = 10, acceptedTypes = '*' }) => { const { upload, isUploading } = useWalrus(); const [dragActive, setDragActive] = useState(false); const [progress, setProgress] = useState(0); const fileInputRef = React.useRef(null); const handleFiles = useCallback(async (files: FileList) => { if (files.length > maxFiles) { alert(`最多只能上传 ${maxFiles} 个文件`); return; } try { setProgress(10); const results = await upload(files); setProgress(100); onUploadComplete?.(results); } catch (error) { alert(`上传失败: ${error.message}`); setProgress(0); } }, [upload, maxFiles, onUploadComplete]); const handleDrop = useCallback((e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setDragActive(false); const files = e.dataTransfer.files; if (files.length > 0) { handleFiles(files); } }, [handleFiles]); const handleChange = useCallback((e: React.ChangeEvent) => { const files = e.target.files; if (files && files.length > 0) { handleFiles(files); } }, [handleFiles]); return (
{ e.preventDefault(); e.stopPropagation(); setDragActive(true); }} onDragLeave={(e) => { e.preventDefault(); e.stopPropagation(); setDragActive(false); }} onDragOver={(e) => { e.preventDefault(); e.stopPropagation(); }} onDrop={handleDrop} onClick={() => fileInputRef.current?.click()} > {isUploading ? (

上传中... {progress}%

) : (
📁

拖拽文件到此处或点击上传

支持最多 {maxFiles} 个文件

)}
); }; // 文件列表组件 export const WalrusFileList: React.FC<{ files: UploadResult[]; onDownload?: (blobId: string, filename: string) => void; }> = ({ files, onDownload }) => { const { download } = useWalrus(); const handleDownload = useCallback(async (blobId: string, filename: string) => { try { await onDownload ? onDownload(blobId, filename) : download(blobId, filename); } catch (error) { alert(`下载失败: ${error.message}`); } }, [download, onDownload]); return (

文件列表

{files.map((file, index) => (
{file.originalName} {file.success ? ( ✓ 上传成功 ) : ( ✗ {file.error} )}
{file.success && file.blobId && (
{file.blobId.slice(0, 16)}...
)}
))}
); }; // 辅助函数 async function uploadFile( file: File, signAndExecuteTransactionBlock: any ): Promise { const arrayBuffer = await file.arrayBuffer(); const walrusFile = WalrusFile.from({ contents: new Uint8Array(arrayBuffer), identifier: `browser/${Date.now()}_${file.name}`, mimeType: file.type, attributes: { 'original-name': file.name, 'file-size': file.size.toString(), 'upload-source': 'browser' } }); const suiClient = new SuiClient({ url: getFullnodeUrl('testnet'), }); const walrusClient = new WalrusClient({ network: 'testnet', suiClient, }); const writeFlow = walrusClient.walrus.writeFilesFlow({ files: [walrusFile], epochs: 10, deletable: true }); const result = await writeFlow.executeWithSigner({ signAndExecuteTransactionBlock }); return { success: true, blobId: result[0].blobId, size: file.size }; } async function downloadFile(blobId: string, filename?: string) { // 实现文件下载逻辑 const link = document.createElement('a'); link.href = `#download-${blobId}`; link.download = filename || 'downloaded-file'; link.click(); } interface UploadResult { success: boolean; blobId?: string; size?: number; originalName: string; index: number; error?: string; } ``` ## 使用方法 ### 基础代码生成 ```typescript skill: "walrus-code-generator" // use-case: basic-upload // framework: nodejs // features: ["error-handling", "logging"] ``` ### React 应用生成 ```typescript skill: "walrus-code-generator" // use-case: browser-app // framework: react // features: ["wallet-integration", "drag-drop", "progress-bar"] ``` ### 高级存储系统 ```typescript skill: "walrus-code-generator" // use-case: advanced-storage // framework: nodejs // features: ["batch-operations", "caching", "retry-logic", "metadata-indexing"] ``` ### 批量处理系统 ```typescript skill: "walrus-code-generator" // use-case: batch-processing // framework: express // features: ["api-endpoints", "queue-system", "monitoring"] ``` ## 生成的代码特性 ### 🛡️ 错误处理 - 智能重试机制 - 详细错误信息 - 优雅降级策略 ### 📊 进度跟踪 - 实时上传进度 - 批量操作状态 - 性能监控 ### 🔧 配置管理 - 灵活的配置选项 - 环境适配 - 类型安全 ### 🚀 性能优化 - 缓存机制 - 并发控制 - 内存管理 ### 🔒 安全考虑 - 输入验证 - 文件完整性检查 - 访问控制 ## 最佳实践 1. **错误处理** - 生成的代码包含完整的错误处理逻辑 2. **类型安全** - 使用 TypeScript 提供完整的类型定义 3. **性能优化** - 包含缓存、批量处理和并发控制 4. **可扩展性** - 模块化设计,易于扩展和维护 5. **监控日志** - 集成日志记录和性能监控 --- *更新时间:2025-11-11*