@cfxdevkit/services 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/LICENSE +72 -0
- package/README.md +257 -0
- package/dist/index.cjs +1097 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1076 -0
- package/dist/index.js.map +1 -0
- package/dist/services/index.cjs +1097 -0
- package/dist/services/index.cjs.map +1 -0
- package/dist/services/index.d.cts +566 -0
- package/dist/services/index.d.ts +566 -0
- package/dist/services/index.js +1076 -0
- package/dist/services/index.js.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/services/encryption.ts","../src/services/keystore.ts","../src/services/swap.ts"],"sourcesContent":["export * from './services/index.js';\n","/*\n * Copyright 2025 Conflux DevKit Team\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { webcrypto } from 'node:crypto';\n\n/**\n * Encryption service using AES-256-GCM\n *\n * Security specifications:\n * - Algorithm: AES-256-GCM (authenticated encryption)\n * - Key derivation: PBKDF2-SHA256 with 100,000 iterations\n * - Salt: 32 bytes (random, stored in keystore)\n * - IV: 12 bytes (random per encryption, prepended to ciphertext)\n * - Format: base64(IV + EncryptedData + AuthTag)\n */\nexport class EncryptionService {\n // Utility class — not meant to be instantiated\n private constructor() {}\n\n private static readonly ITERATIONS = 100000;\n private static readonly KEY_LENGTH = 256;\n private static readonly SALT_LENGTH = 32;\n private static readonly IV_LENGTH = 12;\n\n /**\n * Generate a random salt for key derivation\n */\n static generateSalt(): Buffer {\n return Buffer.from(\n webcrypto.getRandomValues(new Uint8Array(EncryptionService.SALT_LENGTH))\n );\n }\n\n /**\n * Derive encryption key from password using PBKDF2\n */\n static async deriveKey(password: string, salt: Buffer): Promise<CryptoKey> {\n const encoder = new TextEncoder();\n const passwordBuffer = encoder.encode(password);\n\n // Import password as key material\n const keyMaterial = await webcrypto.subtle.importKey(\n 'raw',\n passwordBuffer,\n 'PBKDF2',\n false,\n ['deriveBits', 'deriveKey']\n );\n\n // Derive AES key using PBKDF2\n return await webcrypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: new Uint8Array(salt),\n iterations: EncryptionService.ITERATIONS,\n hash: 'SHA-256',\n },\n keyMaterial,\n { name: 'AES-GCM', length: EncryptionService.KEY_LENGTH },\n false,\n ['encrypt', 'decrypt']\n );\n }\n\n /**\n * Encrypt plaintext with password\n *\n * @param plaintext - String to encrypt\n * @param password - Encryption password\n * @param salt - Salt for key derivation\n * @returns Base64-encoded ciphertext with prepended IV\n */\n static async encrypt(\n plaintext: string,\n password: string,\n salt: Buffer\n ): Promise<string> {\n // Derive key from password\n const key = await EncryptionService.deriveKey(password, salt);\n\n // Generate random IV\n const iv = webcrypto.getRandomValues(\n new Uint8Array(EncryptionService.IV_LENGTH)\n );\n\n // Encode plaintext\n const encoder = new TextEncoder();\n const plaintextBuffer = encoder.encode(plaintext);\n\n // Encrypt with AES-GCM\n const ciphertext = await webcrypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n key,\n plaintextBuffer\n );\n\n // Combine IV + ciphertext (IV prepended for easy extraction)\n const combined = new Uint8Array(iv.length + ciphertext.byteLength);\n combined.set(iv, 0);\n combined.set(new Uint8Array(ciphertext), iv.length);\n\n // Return as base64\n return Buffer.from(combined).toString('base64');\n }\n\n /**\n * Decrypt ciphertext with password\n *\n * @param ciphertext - Base64-encoded ciphertext with prepended IV\n * @param password - Encryption password\n * @param salt - Salt for key derivation\n * @returns Decrypted plaintext\n * @throws Error if decryption fails (wrong password or corrupted data)\n */\n static async decrypt(\n ciphertext: string,\n password: string,\n salt: Buffer\n ): Promise<string> {\n // Decode from base64\n const combined = Buffer.from(ciphertext, 'base64');\n\n // Extract IV and encrypted data\n const iv = combined.subarray(0, EncryptionService.IV_LENGTH);\n const encrypted = combined.subarray(EncryptionService.IV_LENGTH);\n\n // Derive key from password\n const key = await EncryptionService.deriveKey(password, salt);\n\n try {\n // Decrypt with AES-GCM\n const decrypted = await webcrypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n key,\n encrypted\n );\n\n // Decode plaintext\n const decoder = new TextDecoder();\n return decoder.decode(decrypted);\n } catch (_error) {\n throw new Error('Decryption failed - invalid password or corrupted data');\n }\n }\n\n /**\n * Encrypt an object (serializes to JSON first)\n */\n static async encryptObject<T>(\n obj: T,\n password: string,\n salt: Buffer\n ): Promise<string> {\n const json = JSON.stringify(obj);\n return await EncryptionService.encrypt(json, password, salt);\n }\n\n /**\n * Decrypt to an object (parses JSON after decryption)\n */\n static async decryptObject<T>(\n ciphertext: string,\n password: string,\n salt: Buffer\n ): Promise<T> {\n const json = await EncryptionService.decrypt(ciphertext, password, salt);\n return JSON.parse(json) as T;\n }\n\n /**\n * Hash a string with SHA-256 (for config integrity checks)\n */\n static async hash(data: string): Promise<string> {\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(data);\n\n const hashBuffer = await webcrypto.subtle.digest('SHA-256', dataBuffer);\n\n return Buffer.from(hashBuffer).toString('hex');\n }\n\n /**\n * Verify password strength (basic validation)\n */\n static validatePasswordStrength(password: string): {\n valid: boolean;\n errors: string[];\n } {\n const errors: string[] = [];\n\n if (password.length < 8) {\n errors.push('Password must be at least 8 characters');\n }\n\n if (!/[a-z]/.test(password)) {\n errors.push('Password must contain lowercase letters');\n }\n\n if (!/[A-Z]/.test(password)) {\n errors.push('Password must contain uppercase letters');\n }\n\n if (!/[0-9]/.test(password)) {\n errors.push('Password must contain numbers');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n","/*\n * Copyright 2025 Conflux DevKit Team\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Keystore Service V2\n *\n * Complete rewrite for v2.0 with:\n * - Multi-admin support\n * - Per-mnemonic node configuration\n * - Encrypted mnemonic and derived keys storage\n * - Immutable node configuration\n * - No default test mnemonic\n */\n\nimport { createHash } from 'node:crypto';\nimport {\n existsSync,\n readFileSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { logger } from '@cfxdevkit/core/utils';\nimport {\n type DerivedAccount as CoreDerivedAccount,\n deriveAccounts as coreDeriveAccounts,\n generateMnemonic as coreGenerateMnemonic,\n validateMnemonic as coreValidateMnemonic,\n} from '@cfxdevkit/core/wallet';\nimport { EncryptionService } from './encryption.js';\nimport type {\n AddMnemonicData,\n ConfigModificationCheck,\n DerivedAccount,\n KeystoreV2,\n MnemonicEntry,\n MnemonicSummary,\n NodeConfig,\n SetupData,\n} from './keystore-types.js';\n\n// Custom error for locked keystore\nexport class KeystoreLockedError extends Error {\n constructor(\n message: string = 'Keystore is locked. Please unlock with your password first.'\n ) {\n super(message);\n this.name = 'KeystoreLockedError';\n }\n}\n\n// Base data directory for all mnemonic-specific data\nconst BASE_DATA_DIR = process.env.DEVKIT_DATA_DIR || '/workspace/.conflux-dev';\n\n// Keystore file path\nconst DEFAULT_KEYSTORE_PATH =\n process.env.DEVKIT_KEYSTORE_PATH || join(homedir(), '.devkit.keystore.json');\n\n/**\n * KeystoreService V2\n */\nexport class KeystoreService {\n private keystorePath: string;\n private keystore: KeystoreV2 | null = null;\n private currentPassword: string | null = null;\n\n constructor(keystorePath: string = DEFAULT_KEYSTORE_PATH) {\n this.keystorePath = keystorePath;\n }\n\n // ===== PRIVATE GUARD HELPERS =====\n\n private requireKeystore(): KeystoreV2 {\n if (!this.keystore) {\n throw new Error('Keystore not initialized. Call initialize() first.');\n }\n return this.keystore;\n }\n\n private requireEncryptionSalt(): Buffer {\n const ks = this.requireKeystore();\n if (!ks.encryptionSalt) {\n throw new Error('Encryption salt not configured on this keystore.');\n }\n return Buffer.from(ks.encryptionSalt, 'base64');\n }\n\n private requirePassword(): string {\n if (!this.currentPassword) {\n throw new KeystoreLockedError();\n }\n return this.currentPassword;\n }\n\n // ===== INITIALIZATION =====\n\n /**\n * Initialize keystore (load from disk or create empty)\n */\n async initialize(): Promise<void> {\n if (existsSync(this.keystorePath)) {\n await this.loadKeystore();\n } else {\n logger.info('Keystore file not found - fresh installation detected');\n this.keystore = null;\n }\n }\n\n /**\n * Load keystore from disk\n */\n private async loadKeystore(): Promise<void> {\n try {\n const data = readFileSync(this.keystorePath, 'utf-8');\n this.keystore = JSON.parse(data) as KeystoreV2;\n\n // Validate version\n if (this.keystore.version !== 2) {\n throw new Error(\n `Unsupported keystore version: ${this.keystore.version}. Expected version 2.`\n );\n }\n\n logger.info('Keystore loaded successfully');\n } catch (error) {\n logger.error('Failed to load keystore:', error);\n throw error;\n }\n }\n\n /**\n * Save keystore to disk\n */\n private async saveKeystore(): Promise<void> {\n if (!this.keystore) {\n throw new Error('Cannot save null keystore');\n }\n\n try {\n const data = JSON.stringify(this.keystore, null, 2);\n writeFileSync(this.keystorePath, data, 'utf-8');\n logger.info('Keystore saved successfully');\n } catch (error) {\n logger.error('Failed to save keystore:', error);\n throw error;\n }\n }\n\n // ===== SETUP & STATUS =====\n\n /**\n * Check if initial setup is completed\n */\n async isSetupCompleted(): Promise<boolean> {\n return this.keystore?.setupCompleted ?? false;\n }\n\n /**\n * Complete initial setup\n */\n async completeSetup(data: SetupData): Promise<void> {\n if (this.keystore?.setupCompleted) {\n throw new Error('Setup already completed');\n }\n\n logger.info('Completing initial setup...');\n\n // Generate salt if encryption enabled\n let encryptionSalt: Buffer | undefined;\n if (data.encryption?.enabled && data.encryption.password) {\n encryptionSalt = EncryptionService.generateSalt();\n this.currentPassword = data.encryption.password;\n }\n\n // Create mnemonic entry\n const mnemonicEntry = await this.createMnemonicEntry({\n mnemonic: data.mnemonic,\n label: data.mnemonicLabel,\n nodeConfig: {\n ...data.nodeConfig,\n miningAuthor: data.nodeConfig.miningAuthor || 'auto',\n },\n isFirstSetup: true,\n encryptionEnabled: data.encryption?.enabled ?? false,\n encryptionSalt,\n });\n\n // Create keystore v2\n this.keystore = {\n version: 2,\n setupCompleted: true,\n setupCompletedAt: new Date().toISOString(),\n adminAddresses: [data.adminAddress],\n encryptionEnabled: data.encryption?.enabled ?? false,\n encryptionSalt: encryptionSalt?.toString('base64'),\n mnemonics: [mnemonicEntry],\n activeIndex: 0,\n };\n\n await this.saveKeystore();\n\n logger.success('Initial setup completed successfully');\n logger.info(`Admin address: ${data.adminAddress}`);\n logger.info(`Wallet: ${data.mnemonicLabel}`);\n logger.info(\n `Encryption: ${data.encryption?.enabled ? 'Enabled' : 'Disabled'}`\n );\n }\n\n // ===== ADMIN MANAGEMENT =====\n\n /**\n * Get all admin addresses\n */\n async getAdminAddresses(): Promise<string[]> {\n this.ensureKeystoreLoaded();\n return [...(this.keystore?.adminAddresses ?? [])];\n }\n\n /**\n * Add admin address\n */\n async addAdminAddress(address: string): Promise<void> {\n this.ensureKeystoreLoaded();\n\n const normalized = address.toLowerCase();\n const exists = this.keystore?.adminAddresses.some(\n (addr) => addr.toLowerCase() === normalized\n );\n\n if (exists) {\n throw new Error('Admin address already exists');\n }\n\n this.keystore?.adminAddresses.push(address);\n await this.saveKeystore();\n\n logger.info(`Added admin address: ${address}`);\n }\n\n /**\n * Remove admin address\n */\n async removeAdminAddress(\n address: string,\n currentAdmin: string\n ): Promise<void> {\n this.ensureKeystoreLoaded();\n\n // Cannot remove self\n if (address.toLowerCase() === currentAdmin.toLowerCase()) {\n throw new Error('Cannot remove your own admin address');\n }\n\n // Must keep at least one admin\n if (this.requireKeystore().adminAddresses.length <= 1) {\n throw new Error('Cannot remove the last admin address');\n }\n\n const index = this.requireKeystore().adminAddresses.findIndex(\n (addr) => addr.toLowerCase() === address.toLowerCase()\n );\n\n if (index === -1) {\n throw new Error('Admin address not found');\n }\n\n this.requireKeystore().adminAddresses.splice(index, 1);\n await this.saveKeystore();\n\n logger.info(`Removed admin address: ${address}`);\n }\n\n /**\n * Check if address is admin\n */\n isAdmin(address: string): boolean {\n if (!this.keystore) return false;\n\n return this.keystore.adminAddresses.some(\n (admin) => admin.toLowerCase() === address.toLowerCase()\n );\n }\n\n // ===== MNEMONIC MANAGEMENT =====\n\n /**\n * Get active mnemonic entry\n */\n async getActiveMnemonic(): Promise<MnemonicEntry> {\n this.ensureKeystoreLoaded();\n\n const mnemonic =\n this.requireKeystore().mnemonics[this.requireKeystore().activeIndex];\n if (!mnemonic) {\n throw new Error('No active mnemonic found');\n }\n\n return mnemonic;\n }\n\n /**\n * Get mnemonic by ID\n */\n async getMnemonic(id: string): Promise<MnemonicEntry> {\n this.ensureKeystoreLoaded();\n\n const mnemonic = this.requireKeystore().mnemonics.find((m) => m.id === id);\n if (!mnemonic) {\n throw new Error(`Mnemonic not found: ${id}`);\n }\n\n return mnemonic;\n }\n\n /**\n * List all mnemonics (summary only)\n */\n async listMnemonics(): Promise<MnemonicSummary[]> {\n this.ensureKeystoreLoaded();\n\n return this.requireKeystore().mnemonics.map((m, index) => ({\n id: m.id,\n label: m.label,\n type: m.type,\n isActive: index === this.requireKeystore().activeIndex,\n createdAt: m.createdAt,\n nodeConfig: m.nodeConfig,\n dataDir: this.getDataDirForMnemonic(m.mnemonic),\n dataSize: this.getDataDirSize(this.getDataDirForMnemonic(m.mnemonic)),\n }));\n }\n\n /**\n * Add new mnemonic\n */\n async addMnemonic(data: AddMnemonicData): Promise<MnemonicEntry> {\n this.ensureKeystoreLoaded();\n\n // Check for duplicate label\n const exists = this.requireKeystore().mnemonics.some(\n (m) => m.label === data.label\n );\n if (exists) {\n throw new Error(`Mnemonic with label \"${data.label}\" already exists`);\n }\n\n // Create mnemonic entry\n const mnemonicEntry = await this.createMnemonicEntry({\n mnemonic: data.mnemonic,\n label: data.label,\n nodeConfig: {\n ...data.nodeConfig,\n miningAuthor: data.nodeConfig.miningAuthor || 'auto',\n },\n isFirstSetup: false,\n encryptionEnabled: this.requireKeystore().encryptionEnabled,\n encryptionSalt: this.keystore?.encryptionSalt\n ? Buffer.from(this.keystore?.encryptionSalt, 'base64')\n : undefined,\n });\n\n this.requireKeystore().mnemonics.push(mnemonicEntry);\n\n // Set as active if requested\n if (data.setAsActive) {\n this.requireKeystore().activeIndex =\n this.requireKeystore().mnemonics.length - 1;\n }\n\n await this.saveKeystore();\n\n logger.info(`Added mnemonic: ${data.label}`);\n\n return mnemonicEntry;\n }\n\n /**\n * Update mnemonic label\n */\n async updateMnemonicLabel(id: string, label: string): Promise<void> {\n this.ensureKeystoreLoaded();\n\n const index = this.requireKeystore().mnemonics.findIndex(\n (m) => m.id === id\n );\n if (index === -1) {\n throw new Error(`Mnemonic not found: ${id}`);\n }\n\n if (!label.trim()) {\n throw new Error(`Label cannot be empty`);\n }\n\n this.requireKeystore().mnemonics[index].label = label;\n await this.saveKeystore();\n\n logger.info(`Updated label for mnemonic ${id} to: ${label}`);\n }\n\n /**\n * Switch active mnemonic\n */\n async switchActiveMnemonic(id: string): Promise<void> {\n this.ensureKeystoreLoaded();\n\n const index = this.requireKeystore().mnemonics.findIndex(\n (m) => m.id === id\n );\n if (index === -1) {\n throw new Error(`Mnemonic not found: ${id}`);\n }\n\n this.requireKeystore().activeIndex = index;\n await this.saveKeystore();\n\n logger.info(\n `Switched to mnemonic: ${this.requireKeystore().mnemonics[index].label}`\n );\n }\n\n /**\n * Delete mnemonic and its data\n */\n async deleteMnemonic(id: string, deleteData: boolean = false): Promise<void> {\n this.ensureKeystoreLoaded();\n\n const index = this.requireKeystore().mnemonics.findIndex(\n (m) => m.id === id\n );\n if (index === -1) {\n throw new Error(`Mnemonic not found: ${id}`);\n }\n\n // Cannot delete active mnemonic\n if (index === this.requireKeystore().activeIndex) {\n throw new Error(\n 'Cannot delete active mnemonic. Switch to another mnemonic first.'\n );\n }\n\n const mnemonic = this.requireKeystore().mnemonics[index];\n\n // Delete data directory if requested\n if (deleteData) {\n const dataDir = this.getDataDirForMnemonic(mnemonic.mnemonic);\n if (existsSync(dataDir)) {\n // Check for lock file\n const lockFile = join(dataDir, 'node.lock');\n if (existsSync(lockFile)) {\n throw new Error('Cannot delete data while node is running');\n }\n\n rmSync(dataDir, { recursive: true, force: true });\n logger.info(`Deleted data directory: ${dataDir}`);\n }\n }\n\n // Remove from keystore\n this.requireKeystore().mnemonics.splice(index, 1);\n\n // Adjust active index if needed\n if (this.requireKeystore().activeIndex > index) {\n this.requireKeystore().activeIndex--;\n }\n\n await this.saveKeystore();\n\n logger.info(`Deleted mnemonic: ${mnemonic.label}`);\n }\n\n // ===== NODE CONFIGURATION =====\n\n /**\n * Get node configuration for a mnemonic\n */\n async getNodeConfig(mnemonicId: string): Promise<NodeConfig> {\n const mnemonic = await this.getMnemonic(mnemonicId);\n return mnemonic.nodeConfig;\n }\n\n /**\n * Check if node configuration can be modified\n */\n async canModifyNodeConfig(\n mnemonicId: string\n ): Promise<ConfigModificationCheck> {\n const mnemonic = await this.getMnemonic(mnemonicId);\n const dataDir = this.getDataDirForMnemonic(mnemonic.mnemonic);\n\n // Check if data directory exists\n if (!existsSync(dataDir)) {\n return {\n canModify: true,\n };\n }\n\n // Check if node is running (lock file exists)\n const lockFile = join(dataDir, 'node.lock');\n if (existsSync(lockFile)) {\n return {\n canModify: false,\n reason: 'Node is currently running',\n lockFile,\n };\n }\n\n // Data exists but node is stopped\n return {\n canModify: false,\n reason:\n 'Data directory exists. Delete blockchain data to modify configuration.',\n dataDir,\n };\n }\n\n /**\n * Update node configuration\n */\n async updateNodeConfig(\n mnemonicId: string,\n config: Partial<NodeConfig>\n ): Promise<void> {\n const check = await this.canModifyNodeConfig(mnemonicId);\n if (!check.canModify) {\n throw new Error(check.reason);\n }\n\n this.ensureKeystoreLoaded();\n\n const index = this.requireKeystore().mnemonics.findIndex(\n (m) => m.id === mnemonicId\n );\n if (index === -1) {\n throw new Error(`Mnemonic not found: ${mnemonicId}`);\n }\n\n const mnemonic = this.requireKeystore().mnemonics[index];\n\n // Update configuration\n const newConfig: NodeConfig = {\n ...mnemonic.nodeConfig,\n ...config,\n immutable: true,\n configHash: '', // Will be recalculated\n createdAt: new Date().toISOString(),\n };\n\n // Recalculate config hash\n newConfig.configHash = await this.calculateConfigHash(newConfig);\n\n this.requireKeystore().mnemonics[index].nodeConfig = newConfig;\n\n await this.saveKeystore();\n\n logger.info(`Updated node config for: ${mnemonic.label}`);\n }\n\n /**\n * Delete blockchain data directory\n */\n async deleteNodeData(\n mnemonicId: string\n ): Promise<{ deletedDir: string; dataSize: string }> {\n const mnemonic = await this.getMnemonic(mnemonicId);\n const dataDir = this.getDataDirForMnemonic(mnemonic.mnemonic);\n\n if (!existsSync(dataDir)) {\n throw new Error('Data directory does not exist');\n }\n\n // Check for lock file\n const lockFile = join(dataDir, 'node.lock');\n if (existsSync(lockFile)) {\n throw new Error('Cannot delete data while node is running');\n }\n\n const dataSize = this.getDataDirSize(dataDir);\n\n rmSync(dataDir, { recursive: true, force: true });\n\n logger.info(`Deleted data directory: ${dataDir}`);\n\n return { deletedDir: dataDir, dataSize };\n }\n\n // ===== ENCRYPTION =====\n\n /**\n * Check if keystore is locked\n */\n isLocked(): boolean {\n if (!this.keystore || !this.keystore.encryptionEnabled) {\n return false;\n }\n\n return this.currentPassword === null;\n }\n\n /**\n * Check if encryption is enabled for the keystore\n */\n isEncryptionEnabled(): boolean {\n return this.keystore?.encryptionEnabled ?? false;\n }\n\n /**\n * Unlock keystore with password\n */\n async unlockKeystore(password: string): Promise<void> {\n if (!this.keystore || !this.keystore.encryptionEnabled) {\n throw new Error('Keystore is not encrypted');\n }\n\n // Verify password by trying to decrypt first mnemonic\n try {\n const firstMnemonic = this.keystore.mnemonics[0];\n if (firstMnemonic.type === 'encrypted') {\n const salt = this.requireEncryptionSalt();\n await EncryptionService.decrypt(firstMnemonic.mnemonic, password, salt);\n }\n\n this.currentPassword = password;\n logger.info('Keystore unlocked successfully');\n } catch (_error) {\n throw new Error('Invalid password');\n }\n }\n\n /**\n * Lock keystore (clear password from memory)\n */\n async lockKeystore(): Promise<void> {\n this.currentPassword = null;\n logger.info('Keystore locked');\n }\n\n /**\n * Get decrypted mnemonic\n */\n async getDecryptedMnemonic(mnemonicId: string): Promise<string> {\n const mnemonic = await this.getMnemonic(mnemonicId);\n\n if (mnemonic.type === 'plaintext') {\n return mnemonic.mnemonic;\n }\n\n // Encrypted - need password\n if (this.isLocked()) {\n throw new KeystoreLockedError();\n }\n\n const salt = this.requireEncryptionSalt();\n return await EncryptionService.decrypt(\n mnemonic.mnemonic,\n this.requirePassword(),\n salt\n );\n }\n\n // ===== DERIVED KEYS & ACCOUNTS =====\n\n /**\n * Get genesis accounts for a mnemonic\n */\n async deriveGenesisAccounts(mnemonicId: string): Promise<DerivedAccount[]> {\n const mnemonicEntry = await this.getMnemonic(mnemonicId);\n\n // Check if already derived and stored\n if (mnemonicEntry.derivedKeys.type === 'plaintext') {\n return mnemonicEntry.derivedKeys.genesisAccounts as DerivedAccount[];\n }\n\n // Encrypted - need to decrypt\n if (this.isLocked()) {\n throw new KeystoreLockedError();\n }\n\n const salt = this.requireEncryptionSalt();\n const decrypted = await EncryptionService.decryptObject<DerivedAccount[]>(\n mnemonicEntry.derivedKeys.genesisAccounts as string,\n this.requirePassword(),\n salt\n );\n\n return decrypted;\n }\n\n /**\n * Get faucet account for a mnemonic\n */\n async deriveFaucetAccount(mnemonicId: string): Promise<DerivedAccount> {\n const mnemonicEntry = await this.getMnemonic(mnemonicId);\n\n // Check if already derived and stored\n if (mnemonicEntry.derivedKeys.type === 'plaintext') {\n return mnemonicEntry.derivedKeys.faucetAccount as DerivedAccount;\n }\n\n // Encrypted - need to decrypt\n if (this.isLocked()) {\n throw new KeystoreLockedError();\n }\n\n const salt = this.requireEncryptionSalt();\n const decrypted = await EncryptionService.decryptObject<DerivedAccount>(\n mnemonicEntry.derivedKeys.faucetAccount as string,\n this.requirePassword(),\n salt\n );\n\n return decrypted;\n }\n\n /**\n * Derive accounts from mnemonic (HD wallet derivation)\n * Returns accounts with both Core and eSpace private keys\n * Uses @cfxdevkit/core/wallet for derivation\n */\n async deriveAccountsFromMnemonic(\n mnemonic: string,\n _network: 'core' | 'espace', // Kept for API compatibility, both keys are always derived\n count: number,\n startIndex: number = 0,\n chainIdOverride?: number\n ): Promise<DerivedAccount[]> {\n // Get chainId from override or active mnemonic\n let coreNetworkId: number;\n if (chainIdOverride !== undefined) {\n coreNetworkId = chainIdOverride;\n } else {\n const activeMnemonic = await this.getActiveMnemonic();\n coreNetworkId = activeMnemonic.nodeConfig.chainId;\n }\n\n // Use core wallet module for derivation\n const coreAccounts = coreDeriveAccounts(mnemonic, {\n count,\n startIndex,\n coreNetworkId,\n accountType: 'standard',\n });\n\n // Map to backend's DerivedAccount type\n return coreAccounts.map(\n (acc: CoreDerivedAccount): DerivedAccount => ({\n index: acc.index,\n core: acc.coreAddress,\n evm: acc.evmAddress,\n privateKey: acc.corePrivateKey, // Core Space private key (m/44'/503'/0'/0/i)\n evmPrivateKey: acc.evmPrivateKey, // eSpace private key (m/44'/60'/0'/0/i)\n })\n );\n }\n\n // ===== UTILITY METHODS =====\n\n /**\n * Get data directory for active mnemonic\n */\n async getDataDir(): Promise<string> {\n const mnemonic = await this.getActiveMnemonic();\n return this.getDataDirForMnemonic(mnemonic.mnemonic);\n }\n\n /**\n * Get data directory for specific mnemonic\n */\n private getDataDirForMnemonic(mnemonic: string): string {\n const hash = createHash('sha256').update(mnemonic).digest('hex');\n const shortHash = hash.substring(0, 16);\n return join(BASE_DATA_DIR, `wallet-${shortHash}`);\n }\n\n /**\n * Get mnemonic hash (for display)\n */\n async getMnemonicHash(): Promise<string> {\n const mnemonic = await this.getActiveMnemonic();\n const hash = createHash('sha256').update(mnemonic.mnemonic).digest('hex');\n return hash;\n }\n\n /**\n * Get active mnemonic label\n */\n getActiveLabel(): string {\n if (!this.keystore) return 'Unknown';\n const mnemonic = this.keystore.mnemonics[this.keystore.activeIndex];\n return mnemonic?.label || 'Unknown';\n }\n\n /**\n * Get active mnemonic index\n */\n getActiveIndex(): number {\n return this.keystore?.activeIndex ?? 0;\n }\n\n /**\n * Generate new BIP-39 mnemonic\n * Uses @cfxdevkit/core/wallet for generation\n */\n generateMnemonic(): string {\n return coreGenerateMnemonic();\n }\n\n /**\n * Validate mnemonic format\n * Uses @cfxdevkit/core/wallet for validation\n */\n validateMnemonic(mnemonic: string): boolean {\n return coreValidateMnemonic(mnemonic).valid;\n }\n\n // ===== PRIVATE HELPERS =====\n\n /**\n * Ensure keystore is loaded\n */\n private ensureKeystoreLoaded(): void {\n if (!this.keystore) {\n throw new Error('Keystore not loaded. Complete initial setup first.');\n }\n }\n\n /**\n * Create a mnemonic entry with node config and derived keys\n */\n private async createMnemonicEntry(params: {\n mnemonic: string;\n label: string;\n nodeConfig: {\n accountsCount: number;\n chainId: number;\n evmChainId: number;\n miningAuthor: string;\n };\n isFirstSetup: boolean;\n encryptionEnabled: boolean;\n encryptionSalt?: Buffer;\n }): Promise<MnemonicEntry> {\n const { mnemonic, label, nodeConfig, encryptionEnabled, encryptionSalt } =\n params;\n\n const id = `mnemonic_${Date.now()}`;\n const createdAt = new Date().toISOString();\n\n // Derive genesis accounts (0 to accountsCount-1)\n // Pass chainId explicitly since during initial setup there's no active mnemonic yet\n const genesisAccounts = await this.deriveAccountsFromMnemonic(\n mnemonic,\n 'espace',\n nodeConfig.accountsCount,\n 0,\n nodeConfig.chainId\n );\n\n // Derive faucet account (accountsCount)\n const [faucetAccount] = await this.deriveAccountsFromMnemonic(\n mnemonic,\n 'core',\n 1,\n nodeConfig.accountsCount,\n nodeConfig.chainId\n );\n\n // Create node config with hash\n const config: NodeConfig = {\n ...nodeConfig,\n immutable: true,\n configHash: '', // Will be calculated\n createdAt,\n };\n\n config.configHash = await this.calculateConfigHash(config);\n\n // Encrypt mnemonic and derived keys if encryption enabled\n let encryptedMnemonic = mnemonic;\n let derivedKeys: MnemonicEntry['derivedKeys'];\n\n if (encryptionEnabled && encryptionSalt && this.currentPassword) {\n encryptedMnemonic = await EncryptionService.encrypt(\n mnemonic,\n this.currentPassword,\n encryptionSalt\n );\n\n const encryptedGenesis = await EncryptionService.encryptObject(\n genesisAccounts,\n this.currentPassword,\n encryptionSalt\n );\n\n const encryptedFaucet = await EncryptionService.encryptObject(\n faucetAccount,\n this.currentPassword,\n encryptionSalt\n );\n\n derivedKeys = {\n type: 'encrypted',\n genesisAccounts: encryptedGenesis,\n faucetAccount: encryptedFaucet,\n };\n } else {\n derivedKeys = {\n type: 'plaintext',\n genesisAccounts,\n faucetAccount,\n };\n }\n\n return {\n id,\n label,\n type: encryptionEnabled ? 'encrypted' : 'plaintext',\n mnemonic: encryptedMnemonic,\n createdAt,\n nodeConfig: config,\n derivedKeys,\n };\n }\n\n /**\n * Calculate config hash for integrity check\n */\n private async calculateConfigHash(config: NodeConfig): Promise<string> {\n const data = JSON.stringify({\n accountsCount: config.accountsCount,\n chainId: config.chainId,\n evmChainId: config.evmChainId,\n miningAuthor: config.miningAuthor,\n });\n\n return await EncryptionService.hash(data);\n }\n\n /**\n * Get data directory size (human-readable)\n */\n private getDataDirSize(dataDir: string): string {\n if (!existsSync(dataDir)) {\n return '0MB';\n }\n\n try {\n const stats = statSync(dataDir);\n const bytes = stats.size;\n\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n } catch (_error) {\n return '0MB';\n }\n }\n}\n\n// Singleton instance\nlet instance: KeystoreService | null = null;\n\n/**\n * Get singleton KeystoreService instance\n */\nexport function getKeystoreService(): KeystoreService {\n if (!instance) {\n instance = new KeystoreService();\n }\n return instance;\n}\n\n// Re-export types for backward compatibility\nexport type { DerivedAccount } from './keystore-types.js';\n","/*\n * Copyright 2025 Conflux DevKit Team\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Swap Service - Swappi Integration\n *\n * Provides swap operations using Swappi DEX on Conflux eSpace.\n * Swappi is a Uniswap V2-style DEX on Conflux.\n */\n\nimport { logger } from '@cfxdevkit/core/utils';\nimport { type Address, formatUnits, parseUnits } from 'viem';\n\n// Swappi Contract Addresses - Network specific\nconst SWAPPI_CONTRACTS = {\n testnet: {\n FACTORY: '0x8d0d1c7c32d8a395c817B22Ff3BD6fFa2A7eBe08' as Address,\n ROUTER: '0x62B0873055Bf896Dd869e172119871ac24aeA305' as Address,\n },\n mainnet: {\n FACTORY: '0x36B83F9d614a06abF5388F4d14cC64E5FF96892f' as Address,\n ROUTER: '0x62B0873055Bf896Dd869e172119871ac24aeA305' as Address,\n },\n} as const;\n\n// Common token addresses on Conflux eSpace\nconst TOKENS = {\n testnet: {\n WCFX: {\n address: '0x2ed3dddae5b2f321af0806181fbfa6d049be47d8' as Address,\n symbol: 'WCFX',\n name: 'Wrapped CFX',\n decimals: 18,\n },\n USDT: {\n address: '0x7d682e65efc5c13bf4e394b8f376c48e6bae0355' as Address,\n symbol: 'USDT',\n name: 'Tether USD',\n decimals: 18,\n },\n },\n mainnet: {\n WCFX: {\n address: '0x14b2d3bc65e74dae1030eafd8ac30c533c976a9b' as Address,\n symbol: 'WCFX',\n name: 'Wrapped CFX',\n decimals: 18,\n },\n USDT: {\n address: '0xfe97e85d13abd9c1c33384e796f10b73905637ce' as Address,\n symbol: 'USDT',\n name: 'Tether USD',\n decimals: 18,\n },\n USDC: {\n address: '0x6963efed0ab40f6c3d7bda44a05dcf1437c44372' as Address,\n symbol: 'USDC',\n name: 'USD Coin',\n decimals: 18,\n },\n },\n} as const;\n\n// Swappi Router ABI (essential methods only)\nconst SWAPPI_ROUTER_ABI = [\n {\n inputs: [\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMin', type: 'uint256' },\n { name: 'path', type: 'address[]' },\n { name: 'to', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n ],\n name: 'swapExactTokensForTokens',\n outputs: [{ name: 'amounts', type: 'uint256[]' }],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'amountInMax', type: 'uint256' },\n { name: 'path', type: 'address[]' },\n { name: 'to', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n ],\n name: 'swapTokensForExactTokens',\n outputs: [{ name: 'amounts', type: 'uint256[]' }],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n { name: 'amountIn', type: 'uint256' },\n { name: 'path', type: 'address[]' },\n ],\n name: 'getAmountsOut',\n outputs: [{ name: 'amounts', type: 'uint256[]' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'path', type: 'address[]' },\n ],\n name: 'getAmountsIn',\n outputs: [{ name: 'amounts', type: 'uint256[]' }],\n stateMutability: 'view',\n type: 'function',\n },\n] as const;\n\nexport interface SwapQuoteParams {\n tokenIn: Address;\n tokenOut: Address;\n amountIn: string;\n slippage?: number;\n network?: 'testnet' | 'mainnet';\n}\n\nexport interface SwapExecuteParams extends SwapQuoteParams {\n account: number;\n deadline?: number;\n}\n\nexport interface SwapQuote {\n amountIn: string;\n amountOut: string;\n amountOutMin: string;\n path: Address[];\n priceImpact: string;\n slippage: number;\n}\n\nexport interface SwapResult {\n hash: string;\n amountIn: string;\n amountOut: string;\n path: Address[];\n}\n\n/**\n * Minimal interface for the devkit dependency used by SwapService.\n * Only the methods actually consumed by this service are listed.\n */\ninterface SwapDevKit {\n getAccounts(): Record<number, { privateKey: string; evmAddress: string }>;\n}\n\nexport class SwapService {\n constructor(private devkit: SwapDevKit) {}\n\n /**\n * Get swap contracts for network\n */\n private getContracts(network: 'testnet' | 'mainnet' = 'testnet') {\n return SWAPPI_CONTRACTS[network];\n }\n\n /**\n * Get token info\n */\n getToken(symbol: string, network: 'testnet' | 'mainnet' = 'testnet') {\n const tokens = TOKENS[network];\n const token = Object.values(tokens).find((t) => t.symbol === symbol);\n\n if (!token) {\n throw new Error(`Token ${symbol} not found on ${network}`);\n }\n\n return token;\n }\n\n /**\n * List available tokens\n */\n listTokens(network: 'testnet' | 'mainnet' = 'testnet') {\n return Object.values(TOKENS[network]);\n }\n\n /**\n * Get swap quote\n */\n async getQuote(params: SwapQuoteParams): Promise<SwapQuote> {\n try {\n const {\n tokenIn,\n tokenOut,\n amountIn,\n slippage = 0.5,\n network: _network = 'testnet',\n } = params;\n\n // Simple path: tokenIn -> tokenOut\n const path: Address[] = [tokenIn, tokenOut];\n\n // In production, call Swappi router's getAmountsOut\n // For now, simulate quote (assumes 1:1 ratio with 0.3% fee)\n const amountInBN = parseUnits(amountIn, 18);\n const fee = (amountInBN * 3n) / 1000n; // 0.3% fee\n const amountOutBN = amountInBN - fee;\n\n const slippageBN =\n (amountOutBN * BigInt(Math.floor(slippage * 100))) / 10000n;\n const amountOutMinBN = amountOutBN - slippageBN;\n\n return {\n amountIn,\n amountOut: formatUnits(amountOutBN, 18),\n amountOutMin: formatUnits(amountOutMinBN, 18),\n path,\n priceImpact: '0.3',\n slippage,\n };\n } catch (error) {\n logger.error('Failed to get swap quote:', error);\n throw new Error(\n `Failed to get quote: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n /**\n * Execute swap\n */\n async executeSwap(params: SwapExecuteParams): Promise<SwapResult> {\n try {\n const { account, deadline = 20, network = 'testnet' } = params;\n\n // Get quote first\n const quote = await this.getQuote(params);\n\n // Get contracts\n const contracts = this.getContracts(network);\n\n // Get account info\n const accounts = this.devkit.getAccounts();\n const accountInfo = accounts[account];\n\n if (!accountInfo) {\n throw new Error(`Account ${account} not found`);\n }\n\n // Calculate deadline (current time + deadline minutes)\n const _deadlineTimestamp = Math.floor(Date.now() / 1000) + deadline * 60;\n\n // In production, call swapExactTokensForTokens on Swappi router\n // For now, simulate swap execution\n const hash = `0x${Array.from({ length: 64 }, () =>\n Math.floor(Math.random() * 16).toString(16)\n ).join('')}`;\n\n logger.info('Swap executed', {\n hash,\n from: accountInfo.evmAddress,\n router: contracts.ROUTER,\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n });\n\n return {\n hash,\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n path: quote.path,\n };\n } catch (error) {\n logger.error('Swap execution failed:', error);\n throw new Error(\n `Swap failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n\n /**\n * Get Swappi router ABI\n */\n getRouterABI() {\n return SWAPPI_ROUTER_ABI;\n }\n\n /**\n * Get Swappi contract addresses\n */\n getContractAddresses(network: 'testnet' | 'mainnet' = 'testnet') {\n return this.getContracts(network);\n }\n}\n"],"mappings":"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","names":["import_node_crypto","coreDeriveAccounts","coreGenerateMnemonic","coreValidateMnemonic","import_utils"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { AddMnemonicData, ConfigModificationCheck, DerivedAccount, DerivedKeys, EncryptionService, KeystoreLockedError, KeystoreService, KeystoreV2, MnemonicEntry, MnemonicSummary, NodeConfig, SetupData, SwapExecuteParams, SwapQuote, SwapQuoteParams, SwapResult, SwapService, ValidationResult, getKeystoreService } from './services/index.cjs';
|
|
2
|
+
import 'viem';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { AddMnemonicData, ConfigModificationCheck, DerivedAccount, DerivedKeys, EncryptionService, KeystoreLockedError, KeystoreService, KeystoreV2, MnemonicEntry, MnemonicSummary, NodeConfig, SetupData, SwapExecuteParams, SwapQuote, SwapQuoteParams, SwapResult, SwapService, ValidationResult, getKeystoreService } from './services/index.js';
|
|
2
|
+
import 'viem';
|