UNPKG

@m3s/wallet

Version:

A flexible wallet interface supporting multiple blockchain wallet types, including EVM wallets and Web3Auth integration

1,249 lines (1,234 loc) 123 kB
var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // packages/shared/dist/errors/AdapterError.js var AdapterError; var init_AdapterError = __esm({ "packages/shared/dist/errors/AdapterError.js"() { "use strict"; AdapterError = class extends Error { // Add this line constructor(message, options) { super(message); __publicField(this, "code"); __publicField(this, "cause"); __publicField(this, "methodName"); __publicField(this, "details"); this.name = this.constructor.name; this.code = options?.code; this.cause = options?.cause; this.methodName = options?.methodName; this.details = options?.details; console.error(`[AdapterError] ${message}`, { code: this.code, methodName: this.methodName, details: this.details, cause: this.cause, stack: this.stack }); if (typeof Error.captureStackTrace === "function") { Error.captureStackTrace(this, this.constructor); } } }; } }); // packages/shared/dist/registry/capability.js var Capability, MethodToCapabilityMap; var init_capability = __esm({ "packages/shared/dist/registry/capability.js"() { "use strict"; (function(Capability2) { Capability2["CoreWallet"] = "ICoreWallet"; Capability2["EventEmitter"] = "IEventEmitter"; Capability2["MessageSigner"] = "IMessageSigner"; Capability2["TransactionHandler"] = "ITransactionHandler"; Capability2["TypedDataSigner"] = "ITypedDataSigner"; Capability2["GasEstimation"] = "IGasEstimation"; Capability2["TokenOperations"] = "ITokenOperations"; Capability2["RPCHandler"] = "IRPCHandler"; Capability2["TransactionStatus"] = "ITransactionStatus"; Capability2["ContractGenerator"] = "IContractGenerator"; Capability2["ContractCompiler"] = "IContractCompiler"; Capability2["QuoteProvider"] = "IQuoteProvider"; Capability2["OperationHandler"] = "IOperationHandler"; Capability2["ChainDiscovery"] = "IChainDiscovery"; Capability2["GasEstimator"] = "IGasEstimator"; Capability2["OperationMaintenance"] = "IOperationMaintenance"; Capability2["AdapterIdentity"] = "IAdapterIdentity"; Capability2["AdapterLifecycle"] = "IAdapterLifecycle"; })(Capability || (Capability = {})); MethodToCapabilityMap = { // --- ICoreWallet --- "getAccounts": Capability.CoreWallet, "getBalance": Capability.CoreWallet, "getNetwork": Capability.CoreWallet, "setProvider": Capability.CoreWallet, "disconnect": Capability.CoreWallet, "isConnected": Capability.CoreWallet, // --- ITransactionHandler --- "sendTransaction": Capability.TransactionHandler, // --- IMessageSigner --- "signMessage": Capability.MessageSigner, // --- ITypedDataSigner --- "signTypedData": Capability.TypedDataSigner, // --- IGasEstimation --- "estimateGas": Capability.GasEstimation, // --- IEventEmitter --- "on": Capability.EventEmitter, "off": Capability.EventEmitter, "emit": Capability.EventEmitter, // --- ITokenOperations --- "callContract": Capability.TokenOperations, // --- IRPCHandler --- "getChainId": Capability.RPCHandler, "getGasPrice": Capability.RPCHandler, "getBlockNumber": Capability.RPCHandler, // --- ITransactionStatus --- "getTransaction": Capability.TransactionStatus, "waitForTransaction": Capability.TransactionStatus, // --- IContractGenerator --- "generate": Capability.ContractGenerator, // --- IContractCompiler --- "compile": Capability.ContractCompiler, // --- IQuoteProvider --- "getOperationQuote": Capability.QuoteProvider, // --- IOperations --- "executeOperation": Capability.OperationHandler, "getOperationStatus": Capability.OperationHandler, "cancelOperation": Capability.OperationHandler, "resumeOperation": Capability.OperationHandler, // --- IChainDiscovery --- "getSupportedChains": Capability.ChainDiscovery, "getSupportedTokens": Capability.ChainDiscovery, // --- IGasEstimator --- "getGasOnDestination": Capability.GasEstimator, // --- IOperationMaintenance --- "checkForTimedOutOperations": Capability.OperationMaintenance, // --- IAdapterLifecycle --- "initialize": Capability.AdapterLifecycle, "isInitialized": Capability.AdapterLifecycle }; } }); // packages/shared/dist/errors/proxy.js function createErrorHandlingProxy(adapterInstance, capabilities, errorMap = {}, defaultErrorCode, contextName = "UnknownAdapter") { return new Proxy(adapterInstance, { get(target, prop, receiver) { const originalValue = Reflect.get(target, prop, receiver); const methodName = String(prop); if (typeof originalValue === "function") { const requiredCapability = MethodToCapabilityMap[methodName]; if (requiredCapability && !capabilities.includes(requiredCapability)) { return () => { throw new AdapterError(`Method '${methodName}' is not supported by ${contextName}. It lacks the required capability: '${requiredCapability}'.`, { code: "METHOD_NOT_SUPPORTED", methodName }); }; } const isAsync = originalValue.constructor.name === "AsyncFunction"; const handleError = (error) => { const originalErrorMessage = error instanceof Error ? error.message : String(error); console.error(`[${contextName} Error] Method '${methodName}' failed: ${originalErrorMessage}`, error); if (error instanceof AdapterError) { throw error; } let mappedErrorCode = defaultErrorCode; for (const key in errorMap) { if (originalErrorMessage.includes(key)) { mappedErrorCode = errorMap[key]; break; } } throw new AdapterError(`${contextName} method '${methodName}' failed: ${originalErrorMessage}`, { cause: error, methodName, code: mappedErrorCode }); }; if (isAsync) { return async function(...args) { try { return await originalValue.apply(target, args); } catch (error) { handleError(error); } }; } else { return function(...args) { try { return originalValue.apply(target, args); } catch (error) { handleError(error); } }; } } return originalValue; } }); } var init_proxy = __esm({ "packages/shared/dist/errors/proxy.js"() { "use strict"; init_AdapterError(); init_capability(); } }); // packages/shared/dist/errors/index.js var init_errors = __esm({ "packages/shared/dist/errors/index.js"() { "use strict"; init_AdapterError(); init_proxy(); } }); // packages/shared/dist/types/error.js var WalletErrorCode, CrossChainErrorCode, SmartContractErrorCode; var init_error = __esm({ "packages/shared/dist/types/error.js"() { "use strict"; (function(WalletErrorCode2) { WalletErrorCode2["Unknown"] = "UNKNOWN"; WalletErrorCode2["environment"] = "ENVIRONMENT_MISMATCH"; WalletErrorCode2["NotImplemented"] = "NOT_IMPLEMENTED"; WalletErrorCode2["AdapterNotInitialized"] = "ADAPTER_NOT_INITIALIZED"; WalletErrorCode2["WalletNotConnected"] = "WALLET_NOT_CONNECTED"; WalletErrorCode2["ProviderNotFound"] = "PROVIDER_NOT_FOUND"; WalletErrorCode2["NetworkError"] = "NETWORK_ERROR"; WalletErrorCode2["UserRejected"] = "USER_REJECTED"; WalletErrorCode2["InvalidInput"] = "INVALID_INPUT"; WalletErrorCode2["TransactionFailed"] = "TRANSACTION_FAILED"; WalletErrorCode2["SignatureFailed"] = "SIGNATURE_FAILED"; WalletErrorCode2["MethodNotSupported"] = "METHOD_NOT_SUPPORTED"; WalletErrorCode2["FeatureNotSupported"] = "FEATURE_NOT_SUPPORTED"; WalletErrorCode2["AdapterNotFound"] = "ADAPTER_NOT_FOUND"; WalletErrorCode2["MissingConfig"] = "MISSING_CONFIG"; WalletErrorCode2["InitializationFailed"] = "INITIALIZATION_FAILED"; WalletErrorCode2["ConnectionFailed"] = "CONNECTION_FAILED"; WalletErrorCode2["AccountUnavailable"] = "ACCOUNT_UNAVAILABLE"; WalletErrorCode2["GasEstimationFailed"] = "GAS_ESTIMATION_FAILED"; WalletErrorCode2["InsufficientFunds"] = "INSUFFICIENT_FUNDS"; WalletErrorCode2["TransactionReceiptFailed"] = "TRANSACTION_RECEIPT_FAILED"; WalletErrorCode2["TokenBalanceFailed"] = "TOKEN_BALANCE_FAILED"; WalletErrorCode2["SigningFailed"] = "INVALID_SIGNATURE"; WalletErrorCode2["ContractCallFailed"] = "CONTRACT CALL FAILED"; })(WalletErrorCode || (WalletErrorCode = {})); (function(CrossChainErrorCode2) { CrossChainErrorCode2["RpcValidationFailed"] = "RPC_VALIDATION_FAILED"; CrossChainErrorCode2["RpcReliabilityWarning"] = "RPC_RELIABILITY_WARNING"; CrossChainErrorCode2["Unknown"] = "CC_UNKNOWN"; CrossChainErrorCode2["AdapterNotInitialized"] = "CC_ADAPTER_NOT_INITIALIZED"; CrossChainErrorCode2["NetworkError"] = "CC_NETWORK_ERROR"; CrossChainErrorCode2["InvalidInput"] = "CC_INVALID_INPUT"; CrossChainErrorCode2["QuoteFailed"] = "CC_QUOTE_FAILED"; CrossChainErrorCode2["ExecutionFailed"] = "CC_EXECUTION_FAILED"; CrossChainErrorCode2["ProviderSetFailed"] = "CC_PROVIDER_SETUP_FAILED"; CrossChainErrorCode2["StatusCheckFailed"] = "CC_STATUS_CHECK_FAILED"; CrossChainErrorCode2["UnsupportedChain"] = "CC_UNSUPPORTED_CHAIN"; CrossChainErrorCode2["UnsupportedToken"] = "CC_UNSUPPORTED_TOKEN"; CrossChainErrorCode2["OperationNotFound"] = "CC_OPERATION_NOT_FOUND"; })(CrossChainErrorCode || (CrossChainErrorCode = {})); (function(SmartContractErrorCode2) { SmartContractErrorCode2["Unknown"] = "SC_UNKNOWN"; SmartContractErrorCode2["AdapterNotInitialized"] = "SC_ADAPTER_NOT_INITIALIZED"; SmartContractErrorCode2["NetworkError"] = "SC_NETWORK_ERROR"; SmartContractErrorCode2["InvalidInput"] = "SC_INVALID_INPUT"; SmartContractErrorCode2["CompilationFailed"] = "SC_COMPILATION_FAILED"; SmartContractErrorCode2["DeploymentFailed"] = "SC_DEPLOYMENT_FAILED"; SmartContractErrorCode2["MethodCallFailed"] = "SC_METHOD_CALL_FAILED"; SmartContractErrorCode2["ReadCallFailed"] = "SC_READ_CALL_FAILED"; SmartContractErrorCode2["WriteCallFailed"] = "SC_WRITE_CALL_FAILED"; SmartContractErrorCode2["InvalidAbi"] = "SC_INVALID_ABI"; SmartContractErrorCode2["ContractNotFound"] = "SC_CONTRACT_NOT_FOUND"; SmartContractErrorCode2["WalletRequired"] = "SC_WALLET_REQUIRED"; })(SmartContractErrorCode || (SmartContractErrorCode = {})); } }); // packages/shared/dist/types/registry.js var Ms3Modules, RuntimeEnvironment; var init_registry = __esm({ "packages/shared/dist/types/registry.js"() { "use strict"; (function(Ms3Modules2) { Ms3Modules2["wallet"] = "wallet"; Ms3Modules2["smartcontract"] = "smart-contract"; Ms3Modules2["crosschain"] = "crosschain"; })(Ms3Modules || (Ms3Modules = {})); (function(RuntimeEnvironment2) { RuntimeEnvironment2["BROWSER"] = "browser"; RuntimeEnvironment2["SERVER"] = "server"; })(RuntimeEnvironment || (RuntimeEnvironment = {})); } }); // packages/shared/dist/helpers/environment.js function detectRuntimeEnvironment() { const result = []; if (typeof process !== "undefined" && process.versions && process.versions.node) { result.push(RuntimeEnvironment.SERVER); } if (typeof window !== "undefined" && typeof document !== "undefined") { result.push(RuntimeEnvironment.BROWSER); } return result; } function validateEnvironment(adapterName, requirements) { const currentEnvs = detectRuntimeEnvironment(); const isSupported = currentEnvs.some((env) => requirements.supportedEnvironments.includes(env)); if (!isSupported) { const supportedList = requirements.supportedEnvironments.join(", "); const detectedList = currentEnvs.join(", "); let errorMessage = `Adapter '${adapterName}' requires ${supportedList} environment but detected ${detectedList}.`; if (requirements.limitations) { errorMessage += "\n" + requirements.limitations.join("\n"); } throw new AdapterError(errorMessage, { code: WalletErrorCode.environment, methodName: "validateEnvironment", details: { adapterName, currentEnvironment: currentEnvs, // ✅ Now array supportedEnvironments: requirements.supportedEnvironments, limitations: requirements.limitations } }); } if (requirements.securityNotes && requirements.securityNotes.length > 0) { requirements.securityNotes.forEach((note) => { console.warn(`[${adapterName}] Security Note: ${note}`); }); } } var init_environment = __esm({ "packages/shared/dist/helpers/environment.js"() { "use strict"; init_AdapterError(); init_error(); init_registry(); } }); // packages/shared/dist/registry/compatibility.js function getStaticCompatibilityMatrix(moduleName, adapterName, version) { const key = `${adapterName}@${version}`; switch (moduleName) { case "wallet": return WALLET_COMPATIBILITY[key]; case "smart-contract": return SMART_CONTRACT_COMPATIBILITY[key]; case "crosschain": return CROSSCHAIN_COMPATIBILITY[key]; default: return void 0; } } function checkCrossPackageCompatibility(sourceModule, sourceAdapter, sourceVersion, targetModule, targetAdapter, targetVersion) { const sourceMatrix = getStaticCompatibilityMatrix(sourceModule, sourceAdapter, sourceVersion); if (!sourceMatrix) return false; const targetModuleCompatRule = sourceMatrix.crossModuleCompatibility.find((cmc) => cmc.moduleName === targetModule); if (!targetModuleCompatRule) return false; const targetAdapterInfo = registry.getAdapter(targetModule, targetAdapter, targetVersion); if (!targetAdapterInfo?.capabilities) return false; const sourceAdapterInfo = registry.getAdapter(sourceModule, sourceAdapter, sourceVersion); const currentEnvironments = detectRuntimeEnvironment(); if (sourceAdapterInfo?.environment && !sourceAdapterInfo.environment.supportedEnvironments.some((env) => currentEnvironments.includes(env))) { return false; } if (targetAdapterInfo.environment && !targetAdapterInfo.environment.supportedEnvironments.some((env) => currentEnvironments.includes(env))) { return false; } return targetModuleCompatRule.requiresCapabilities.every((requiredCap) => targetAdapterInfo.capabilities.includes(requiredCap)); } var WALLET_COMPATIBILITY, SMART_CONTRACT_COMPATIBILITY, CROSSCHAIN_COMPATIBILITY; var init_compatibility = __esm({ "packages/shared/dist/registry/compatibility.js"() { "use strict"; init_environment(); init_capability(); init_registry2(); WALLET_COMPATIBILITY = { "ethers@1.0.0": { adapterName: "ethers", version: "1.0.0", compatibleVersions: ["1.0.0"], breakingChanges: [], crossModuleCompatibility: [ { moduleName: "smart-contract", // ✅ This wallet can work with any smart-contract adapter that can generate contracts. requiresCapabilities: [Capability.ContractGenerator] }, { moduleName: "crosschain", // ✅ This wallet can work with any crosschain adapter that can execute operations. requiresCapabilities: [Capability.OperationHandler] } ] }, "web3auth@1.0.0": { adapterName: "web3auth", version: "1.0.0", compatibleVersions: ["1.0.0"], breakingChanges: [], crossModuleCompatibility: [ { moduleName: "smart-contract", // ✅ This wallet can work with any smart-contract adapter that can generate contracts. requiresCapabilities: [Capability.ContractGenerator] }, { moduleName: "crosschain", // ✅ This wallet can work with any crosschain adapter that can execute operations. requiresCapabilities: [Capability.OperationHandler] } ] } }; SMART_CONTRACT_COMPATIBILITY = { "openZeppelin@1.0.0": { adapterName: "openZeppelin", version: "1.0.0", compatibleVersions: ["1.0.0"], breakingChanges: [], crossModuleCompatibility: [ { moduleName: "wallet", // ✅ This smart-contract adapter needs a wallet that can handle transactions. requiresCapabilities: [Capability.TransactionHandler, Capability.RPCHandler] } ] } }; CROSSCHAIN_COMPATIBILITY = { "lifi@1.0.0": { adapterName: "lifi", version: "1.0.0", compatibleVersions: ["1.0.0"], breakingChanges: [], crossModuleCompatibility: [ { moduleName: "wallet", // ✅ This crosschain adapter needs a wallet that can handle transactions and RPC calls. requiresCapabilities: [Capability.TransactionHandler, Capability.RPCHandler] } ] } }; } }); // packages/shared/dist/registry/registry.js function getPropertyByPath(obj, path) { return path.split(".").reduce((currentObject, key) => { return currentObject && typeof currentObject === "object" && Object.prototype.hasOwnProperty.call(currentObject, key) ? currentObject[key] : void 0; }, obj); } var UniversalRegistry, registry; var init_registry2 = __esm({ "packages/shared/dist/registry/registry.js"() { "use strict"; init_compatibility(); UniversalRegistry = class { constructor() { __publicField(this, "modules", /* @__PURE__ */ new Map()); __publicField(this, "adapters", /* @__PURE__ */ new Map()); __publicField(this, "compatibilityMatrices", /* @__PURE__ */ new Map()); __publicField(this, "interfaceShapes", /* @__PURE__ */ new Map()); } // ✅ ADD: The missing map /** * ✅ NEW: Register the shape of a convenience alias. * This is called by modules (e.g., wallet/index.ts) to define their aliases. * @param interfaceName The name of the alias (e.g., 'IEVMWallet'). * @param requiredCapabilities An array of base capability names it requires. */ registerInterfaceShape(interfaceName, requiredCapabilities) { this.interfaceShapes.set(interfaceName, requiredCapabilities); } /** * ✅ NEW: Get the shape of a convenience alias. * This is called by the validator to verify an adapter meets an interface's requirements. */ getInterfaceShape(interfaceName) { return this.interfaceShapes.get(interfaceName); } /** * ✅ NEW: A modern replacement for findAdaptersWithFeature that uses our new architecture. * Finds all adapters that have a specific capability. */ findAdaptersWithCapability(capability) { const result = []; for (const moduleAdapters of this.adapters.values()) { for (const metadata of moduleAdapters.values()) { if (metadata.capabilities?.includes(capability)) { result.push(metadata); } } } return result; } /** * Get compatibility matrix for an adapter */ getCompatibilityMatrix(moduleName, name, version) { const moduleMatrices = this.compatibilityMatrices.get(moduleName); if (!moduleMatrices) return void 0; const key = `${name}@${version}`; return moduleMatrices.get(key); } /** * Get latest version of an adapter */ getLatestVersion(moduleName, name) { const latest = this.getLatestAdapter(moduleName, name); return latest?.version; } /** * Register a compatibility matrix for an adapter */ registerCompatibilityMatrix(moduleName, matrix) { if (!this.compatibilityMatrices.has(moduleName)) { this.compatibilityMatrices.set(moduleName, /* @__PURE__ */ new Map()); } const moduleMatrices = this.compatibilityMatrices.get(moduleName); const key = `${matrix.adapterName}@${matrix.version}`; moduleMatrices.set(key, matrix); } /** * Check compatibility between adapter versions */ checkAdapterCompatibility(moduleName, name, versions) { const report = { compatible: true, conflicts: [], recommendations: [], supportedVersions: [] }; const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) { report.compatible = false; report.conflicts.push({ type: "version", severity: "error", description: `Module '${moduleName}' not found`, affectedVersions: versions }); return report; } for (const version of versions) { const adapter = this.getAdapter(moduleName, name, version); if (!adapter) { report.compatible = false; report.conflicts.push({ type: "version", severity: "error", description: `Adapter '${name}' version '${version}' not found`, affectedVersions: [version] }); continue; } report.supportedVersions.push(version); const matrix = this.getCompatibilityMatrix(moduleName, name, version); if (matrix) { for (const otherVersion of versions) { if (version !== otherVersion) { const breakingChange = matrix.breakingChanges.find((bc) => bc.fromVersion === otherVersion || bc.toVersion === otherVersion); if (breakingChange) { report.conflicts.push({ type: "breaking-change", severity: "warning", description: `Breaking changes between ${breakingChange.fromVersion} and ${breakingChange.toVersion}: ${breakingChange.changes.join(", ")}`, affectedVersions: [breakingChange.fromVersion, breakingChange.toVersion], suggestedAction: breakingChange.migrationPath }); } } } } } if (report.conflicts.length === 0) { report.recommendations.push("All specified versions are compatible"); } else { const latestVersion = this.getLatestVersion(moduleName, name); if (latestVersion) { report.recommendations.push(`Consider using latest version: ${latestVersion}`); } } return report; } /** * Get adapters compatible with a specific adapter instance */ getCompatibleAdapters(currentAdapter, targetModuleName) { const compatibleAdapters = []; const modulesToCheck = targetModuleName ? [targetModuleName] : Array.from(this.adapters.keys()); for (const moduleName of modulesToCheck) { if (moduleName === currentAdapter.moduleName) continue; const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) continue; for (const [, targetAdapterMetadata] of moduleAdapters) { const isCompatible = checkCrossPackageCompatibility(currentAdapter.moduleName, currentAdapter.name, currentAdapter.version, targetAdapterMetadata.module, targetAdapterMetadata.name, targetAdapterMetadata.version); if (isCompatible) { compatibleAdapters.push(targetAdapterMetadata); } } } return compatibleAdapters; } /** * Batch register adapters with atomic rollback */ registerAdapters(adapters) { const originalState = new Map(this.adapters); try { for (const adapter of adapters) { this.registerAdapter(adapter.module, adapter); } } catch (error) { this.adapters = originalState; throw new Error(`Batch registration failed: ${error}. State rolled back.`); } } /** * Register a module in the registry */ registerModule(metadata) { this.modules.set(metadata.name, metadata); if (!this.adapters.has(metadata.name)) { this.adapters.set(metadata.name, /* @__PURE__ */ new Map()); } } /** * Register an adapter for a specific module */ registerAdapter(moduleName, metadata) { if (!this.modules.has(moduleName)) { const moduleMetadata = { name: moduleName, version: metadata.version // Use adapter's version as default module version }; this.registerModule(moduleMetadata); } const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) { throw new Error(`Module ${moduleName} not properly initialized in registry`); } const adapterKey = `${metadata.name}@${metadata.version}`; moduleAdapters.set(adapterKey, metadata); } /** * Get an adapter by module and adapter name */ getAdapter(moduleName, name, version) { const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) return void 0; const adapterKey = `${name}@${version}`; return moduleAdapters.get(adapterKey); } /** * Get the latest version of an adapter by name */ getLatestAdapter(moduleName, name) { const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) return void 0; const matchingAdapters = []; for (const [, metadata] of moduleAdapters.entries()) { if (metadata.name === name) { matchingAdapters.push(metadata); } } if (matchingAdapters.length === 0) return void 0; matchingAdapters.sort((a, b) => b.version.localeCompare(a.version)); return matchingAdapters[0]; } /** * Get all adapters for a module */ getModuleAdapters(moduleName) { const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) return []; return Array.from(moduleAdapters.values()); } /** * Get all available versions of a specific adapter */ getAdapterVersions(moduleName, name) { const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) return []; const versions = []; for (const [, metadata] of moduleAdapters.entries()) { if (metadata.name === name) { versions.push(metadata.version); } } return versions.sort((a, b) => b.localeCompare(a)); } /** * Get all modules */ getAllModules() { return Array.from(this.modules.values()); } /** * Get environment requirements for an adapter */ getEnvironmentRequirements(moduleName, name, version) { const adapter = this.getAdapter(moduleName, name, version); return adapter?.environment; } /** * Check if an adapter supports a specific environment */ supportsEnvironment(moduleName, name, version, environment) { const adapter = this.getAdapter(moduleName, name, version); if (!adapter || !adapter.environment) return true; return adapter.environment.supportedEnvironments.includes(environment); } /** * Get adapters that support a specific environment */ getAdaptersByEnvironment(moduleName, environment) { const moduleAdapters = this.adapters.get(moduleName); if (!moduleAdapters) return []; const result = []; for (const [, metadata] of moduleAdapters.entries()) { if (!metadata.environment || metadata.environment.supportedEnvironments.includes(environment)) { result.push(metadata); } } return result; } }; registry = new UniversalRegistry(); } }); // packages/shared/dist/registry/index.js var init_registry3 = __esm({ "packages/shared/dist/registry/index.js"() { "use strict"; init_registry2(); init_compatibility(); init_capability(); } }); // packages/shared/dist/types/base.js var init_base = __esm({ "packages/shared/dist/types/base.js"() { "use strict"; } }); // packages/shared/dist/types/index.js var init_types = __esm({ "packages/shared/dist/types/index.js"() { "use strict"; init_registry(); init_error(); init_base(); } }); // packages/shared/dist/helpers/network.js import { BrowserProvider, JsonRpcProvider } from "ethers"; var staticChainList, _NetworkHelper, NetworkHelper; var init_network = __esm({ "packages/shared/dist/helpers/network.js"() { "use strict"; init_AdapterError(); init_error(); staticChainList = [ { name: "Ethereum Mainnet", chainId: 1, shortName: "eth", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpc: [ "https://eth.llamarpc.com", "https://ethereum-rpc.publicnode.com", "https://1rpc.io/eth", "https://cloudflare-eth.com" ], blockExplorerUrl: "https://etherscan.io", isTestnet: false, isStatic: true }, { name: "Polygon Mainnet", chainId: 137, shortName: "matic", nativeCurrency: { name: "MATIC", symbol: "MATIC", decimals: 18 }, rpc: [ "https://polygon-rpc.com", "https://polygon.llamarpc.com", "https://polygon.drpc.org" ], blockExplorerUrl: "https://polygonscan.com", isTestnet: false, isStatic: true }, { name: "Optimism", chainId: 10, shortName: "oeth", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpc: [ "https://mainnet.optimism.io", "https://optimism.llamarpc.com", "https://optimism.publicnode.com" ], blockExplorerUrl: "https://optimistic.etherscan.io", isTestnet: false, isStatic: true }, { name: "Arbitrum One", chainId: 42161, shortName: "arb1", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpc: [ "https://arb1.arbitrum.io/rpc", "https://arbitrum.llamarpc.com", "https://arbitrum-one.public.blastapi.io" ], blockExplorerUrl: "https://arbiscan.io", isTestnet: false, isStatic: true }, { name: "Holesky", chainId: 17e3, shortName: "holesky", nativeCurrency: { name: "Holesky Ether", symbol: "ETH", decimals: 18 }, rpc: ["https://ethereum-holesky.publicnode.com"], blockExplorerUrl: "https://holesky.etherscan.io", isTestnet: true, isStatic: true }, { name: "Sepolia", chainId: 11155111, shortName: "sep", nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 }, rpc: [ "https://rpc.sepolia.org", "https://ethereum-sepolia-rpc.publicnode.com", "https://endpoints.omniatech.io/v1/eth/sepolia/public", "https://eth-sepolia.public.blastapi.io" ], blockExplorerUrl: "https://sepolia.etherscan.io", isTestnet: true, isStatic: true } ]; _NetworkHelper = class _NetworkHelper { constructor() { __publicField(this, "networkCache", {}); __publicField(this, "initializationPromise", null); for (const chain of staticChainList) { this.addChainToCache(chain); } } static getInstance() { if (!_NetworkHelper.instance) { _NetworkHelper.instance = new _NetworkHelper(); } return _NetworkHelper.instance; } /** * Ensures that the initial loading of networks has attempted to complete. */ async ensureInitialized() { if (!this.initializationPromise) { this.initializationPromise = this.fetchAndMergeExternalChainList(); } await this.initializationPromise; } async fetchAndMergeExternalChainList() { try { const response = await fetch("https://chainid.network/chains.json"); if (!response.ok) { throw new Error(`Failed to fetch chain list: ${response.statusText}`); } const externalChains = await response.json(); for (const chain of externalChains) { const normalizedId = _NetworkHelper.normalizeChainId(chain.chainId); if (!this.networkCache[normalizedId] || !this.networkCache[normalizedId].isStatic) { this.addChainToCache(chain, false); } } } catch (error) { console.warn("[NetworkHelper] Could not fetch external chain list. Using embedded static list only.", error); } } addChainToCache(chain, isStatic = true) { if (!chain || !chain.chainId) return; const normalizedId = _NetworkHelper.normalizeChainId(chain.chainId); const rpcUrls = (chain.rpc || []).filter((url) => url && url.startsWith("http") && !url.includes("${")); if (rpcUrls.length === 0 && !isStatic) return; const config = { name: chain.name, chainId: normalizedId, shortName: chain.shortName, nativeCurrency: chain.nativeCurrency, rpcUrls, blockExplorerUrl: chain.explorers?.[0]?.url || chain.blockExplorerUrl, // isTestnet: chain.isTestnet ?? (chain.networkId !== 1), // Simple heuristic isStatic, displayName: chain.name, decimals: chain.nativeCurrency?.decimals || 18, ticker: chain.nativeCurrency?.symbol, tickerName: chain.nativeCurrency?.name }; this.networkCache[normalizedId] = config; this.networkCache[chain.chainId.toString()] = config; if (chain.shortName) { this.networkCache[chain.shortName.toLowerCase()] = config; } if (chain.name) { this.networkCache[chain.name.toLowerCase().replace(/\s+/g, "")] = config; } } async getNetworkConfig(networkIdentifier, preferredRpcUrls = [], useOnlyPreferredRpc = false) { await this.ensureInitialized(); const identifierStr = String(networkIdentifier).toLowerCase().replace(/\s+/g, ""); const baseConfig = this.networkCache[identifierStr]; if (!baseConfig || !baseConfig.chainId) { return null; } const uniquePreferred = [...new Set(preferredRpcUrls.filter((url) => url))]; const baseRpcUrls = Array.isArray(baseConfig.rpcUrls) ? baseConfig.rpcUrls : []; let urlsToTest = []; if (useOnlyPreferredRpc) { if (uniquePreferred.length === 0) { console.warn(`[NetworkHelper] getNetworkConfig called with useOnlyPreferredRpc=true but no preferredRpcUrls were provided for ${networkIdentifier}.`); return null; } urlsToTest = uniquePreferred; } else { urlsToTest = [...uniquePreferred, ...baseRpcUrls.filter((url) => !uniquePreferred.includes(url))]; } if (urlsToTest.length === 0) { return null; } const workingUrl = await this.findFirstWorkingRpc(urlsToTest, baseConfig.chainId); if (!workingUrl) { return null; } if (!useOnlyPreferredRpc && uniquePreferred.length > 0 && !uniquePreferred.includes(workingUrl)) { console.warn(`[NetworkHelper] None of the preferred RPCs worked for ${baseConfig.name}. Using a public RPC: ${workingUrl}. For critical operations, ensure your preferred RPCs are operational.`); } const orderedRpcUrls = [workingUrl, ...urlsToTest.filter((url) => url !== workingUrl)]; return { chainId: baseConfig.chainId, name: baseConfig.name, displayName: baseConfig.displayName || baseConfig.name, rpcUrls: orderedRpcUrls, decimals: baseConfig.decimals, blockExplorerUrl: baseConfig.blockExplorerUrl, ticker: baseConfig.ticker, tickerName: baseConfig.tickerName, shortName: baseConfig.shortName }; } async testRpcConnection(url, expectedChainId, timeoutMs = 5e3) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), timeoutMs); try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", method: "eth_chainId", params: [], id: 1 }), signal: controller.signal }); if (!response.ok) { return false; } const data = await response.json(); if (data.error) { return false; } const receivedChainId = _NetworkHelper.normalizeChainId(data.result); const expectedNormalized = _NetworkHelper.normalizeChainId(expectedChainId); if (receivedChainId !== expectedNormalized) { console.warn(`[testRpcConnection] Chain ID mismatch for ${url}: Got ${receivedChainId}, Expected ${expectedNormalized}`); return false; } return true; } catch (error) { if (error.name === "AbortError") { } else { } return false; } finally { clearTimeout(timeout); } } async findFirstWorkingRpc(urls, expectedChainId, timeoutMs = 3e3) { for (const url of urls) { if (await this.testRpcConnection(url, expectedChainId, timeoutMs)) { return url; } } return null; } async getProvider(input, preferredRpcUrls = [], chainId) { if (input instanceof JsonRpcProvider || input instanceof BrowserProvider) { return input; } if (input && typeof input.request === "function") { return new BrowserProvider(input, "any"); } if (typeof input === "string") { return new JsonRpcProvider(input); } if (input && typeof input === "object" && Array.isArray(input.rpcUrls) && input.rpcUrls.length > 0) { return new JsonRpcProvider(input.rpcUrls[0]); } if (!chainId) { throw new AdapterError("No chainId available to pick a public RPC. Supply your own in options.provider.", { code: WalletErrorCode.InvalidInput, methodName: "getProvider" }); } const net = await this.getNetworkConfig(chainId, preferredRpcUrls); if (!net || !net.rpcUrls || net.rpcUrls.length === 0) { throw new AdapterError(`No RPC could be reached for chainId=${chainId}. Please supply at least one working URL in options.provider.rpcUrls.`, { code: WalletErrorCode.ConnectionFailed, methodName: "getProvider" }); } return new JsonRpcProvider(net.rpcUrls[0]); } static normalizeChainId(chainId) { if (typeof chainId === "number") { return `0x${chainId.toString(16).toLowerCase()}`; } if (typeof chainId === "string") { if (chainId.toLowerCase().startsWith("0x")) { return chainId.toLowerCase(); } const num = parseInt(chainId, 10); if (!isNaN(num)) { return `0x${num.toString(16).toLowerCase()}`; } } throw new AdapterError(`Invalid chainId format: ${chainId}`, { code: WalletErrorCode.InvalidInput }); } static assertConfigIsValid(config, context = "NetworkConfiguration") { if (!config) { throw new Error(`[NetworkHelper] ${context}: Configuration is null or undefined.`); } if (!config.chainId) { throw new Error(`[NetworkHelper] ${context} (Name: ${config.name || "N/A"}): Missing chainId.`); } if (!config.rpcUrls || config.rpcUrls.length === 0) { throw new Error(`[NetworkHelper] ${context} (Name: ${config.name || "N/A"}, ChainID: ${config.chainId}): Missing or empty rpcUrls.`); } return config; } static filterValidConfigs(configs) { const isValid = (config) => !!config && !!config.chainId && Array.isArray(config.rpcUrls) && config.rpcUrls.length > 0; if (Array.isArray(configs)) { return configs.filter(isValid); } else { const result = {}; for (const key in configs) { if (Object.prototype.hasOwnProperty.call(configs, key)) { const config = configs[key]; if (isValid(config)) { result[key] = config; } } } return result; } } validatePrivateRpcsForChains(chainIds, walletRpcs) { const missingChains = []; for (const chainId of chainIds) { const normalizedId = _NetworkHelper.normalizeChainId(chainId); const decimalId = parseInt(normalizedId, 16).toString(); const hasRpcs = walletRpcs[normalizedId]?.length > 0 || walletRpcs[decimalId]?.length > 0; if (!hasRpcs) { missingChains.push(decimalId); } } return { hasAllPrivateRpcs: missingChains.length === 0, missingChains }; } }; __publicField(_NetworkHelper, "instance"); NetworkHelper = _NetworkHelper; } }); // packages/shared/dist/helpers/keys.js import { Wallet as EthersWallet, HDNodeWallet, Mnemonic, Wallet, isHexString } from "ethers"; var PrivateKeyHelper; var init_keys = __esm({ "packages/shared/dist/helpers/keys.js"() { "use strict"; PrivateKeyHelper = class { /** * Generates a new random EVM-compatible private key. * @returns A string representing the private key (hexadecimal, 0x-prefixed). */ generatePrivateKey() { try { const wallet = EthersWallet.createRandom(); return wallet.privateKey; } catch (error) { throw new Error(`[PrivateKeyHelper.generatePrivateKey] Failed: ${error.message}`); } } /** * Encrypts an EVM private key into a JSON keystore (EIP-2335 format) using a password. * @param privateKey The EVM private key string (hexadecimal, 0x-prefixed). * @param password The password for encryption. * @returns A promise resolving to the JSON keystore string. * @throws Error if the private key is invalid or encryption fails. */ async encryptPrivateKey(privateKey, password) { if (!this.isValidEvmPrivateKey(privateKey)) { throw new Error("[PrivateKeyHelper.encryptPrivateKey] Invalid private key format."); } try { const wallet = new EthersWallet(privateKey); const jsonKeystore = await wallet.encrypt(password); return jsonKeystore; } catch (error) { throw new Error(`[PrivateKeyHelper.encryptPrivateKey] Encryption failed: ${error.message}`); } } /** * Decrypts an EVM JSON keystore using a password. * @param encryptedJsonKeystore The JSON keystore string. * @param password The password for decryption. * @returns A promise resolving to the decrypted EVM private key string. * @throws Error if decryption fails (e.g., invalid keystore, incorrect password). */ async decryptPrivateKey(encryptedJsonKeystore, password) { try { const wallet = await EthersWallet.fromEncryptedJson(encryptedJsonKeystore, password); return wallet.privateKey; } catch (error) { throw new Error(`[PrivateKeyHelper.decryptPrivateKey] Decryption failed: ${error.message}`); } } /** * Derives the public Ethereum address from an EVM private key. * @param privateKey The EVM private key string (hexadecimal, 0x-prefixed). * @returns The corresponding public address string. * @throws Error if the private key is invalid. */ getAddressFromPrivateKey(privateKey) { if (!this.isValidEvmPrivateKey(privateKey)) { throw new Error("[PrivateKeyHelper.getAddressFromPrivateKey] Invalid private key format."); } try { const wallet = new EthersWallet(privateKey); return wallet.address; } catch (error) { throw new Error(`[PrivateKeyHelper.getAddressFromPrivateKey] Failed to derive address: ${error.message}`); } } /** * Generates a new random BIP39 mnemonic phrase. * Uses ethers.Wallet.createRandom() for robust generation. * @returns A randomly generated mnemonic phrase (typically 12 words). * @throws Error if mnemonic generation fails. */ generateMnemonic() { try { const randomWallet = Wallet.createRandom(); if (!randomWallet.mnemonic || !randomWallet.mnemonic.phrase) { throw new Error("Failed to generate mnemonic phrase from random wallet."); } return randomWallet.mnemonic.phrase; } catch (error) { const wrappedError = new Error(`[PrivateKeyHelper.generateMnemonic] Failed during mnemonic generation: ${error.message}`); if (error.stack) { wrappedError.stack = error.stack; } wrappedError.cause = error; throw wrappedError; } } /** * Derives an EVM private key from a mnemonic phrase and an optional HD path. * @param mnemonic The BIP-39 mnemonic phrase. * @param path The HD path (e.g., "m/44'/60'/0'/0/0"). Defaults to the standard Ethereum path. * @returns The derived private key string. * @throws Error if the mnemonic is invalid or derivation fails. */ getPrivateKeyFromMnemonic(mnemonic, path) { const hdPath = path || "m/44'/60'/0'/0/0"; try { if (!Mnemonic.isValidMnemonic(mnemonic)) { throw new Error("Invalid mnemonic phrase provided."); } const mnemonicInstance = Mnemonic.fromPhrase(mnemonic); const hdNode = HDNodeWallet.fromMnemonic(mnemonicInstance, hdPath); return hdNode.privateKey; } catch (error) { throw new Error(`[PrivateKeyHelper.getPrivateKeyFromMnemonic] Failed: ${error.message}`); } } /** * Validates if the given string is a plausible EVM private key format. * (Basic check for 0x prefix and 64 hex characters). * @param privateKey The string to validate. * @returns True if it matches the basic format, false otherwise. */ isValidEvmPrivateKey(privateKey) { return typeof privateKey === "string" && isHexString(privateKey, 32); } }; } }); // packages/shared/dist/helpers/validator.js function validateAdapterParameters(args) { const { name, version, params, adapterInfo, registry: registry2, factoryMethodName } = args; const { expectedInterface } = params; console.log("Validator - arguments, ", args); if (expectedInterface) { const requiredCapabilities = registry2.getInterfaceShape(expectedInterface); if (!requiredCapabilities) { throw new AdapterError(`Unknown interface shape requested: '${expectedInterface}'. Ensure it is registered in the registry.`, { code: "INTERNAL_ERROR" }); } const adapterCapabilities = adapterInfo.capabilities || []; for (const req of requiredCapabilities) { if (!adapterCapabilities.includes(req)) { throw new AdapterError(`Adapter '${name}@${version}' does not fully implement the '${expectedInterface}' interface. Missing capability: '${req}'.`, { code: "INCOMPATIBLE_ADAPTER", methodName: factoryMethodName }); } } } if (adapterInfo.requirements && adapterInfo.requirements.length > 0) { console.log("Validator - adapterInfo, ", adapterInfo); for (const req of adapterInfo.requirements) { const value = getPropertyByPath(params, req.path); if (value === void 0 && !req.allowUndefined) { const errorMessage = req.message || `Required option '${req.path}' is missing for adapter '${name}'.`; throw new AdapterError(errorMessage, { methodName: factoryMethodName, code: "MISSING_ADAPTER_REQUIREMENT", details: { path: req.path, message: req.message } }); } if (req.type && value !== void 0) { const valueType = Array.isArray(value) ? "array" : typeof value; if (valueType !== req.ty