@m3s/smart-contract
Version:
A modular toolkit for generating, compiling, deploying, and interacting with Ethereum-compatible smart contracts
1,226 lines (1,213 loc) • 90.1 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// packages/smart-contract/dist/index.js
var index_exports = {};
__export(index_exports, {
AdapterError: () => AdapterError,
ContractHandlerType: () => ContractHandlerType,
NetworkHelper: () => NetworkHelper,
PrivateKeyHelper: () => PrivateKeyHelper,
RuntimeEnvironment: () => RuntimeEnvironment,
SmartContractErrorCode: () => SmartContractErrorCode,
WalletErrorCode: () => WalletErrorCode,
createContractHandler: () => createContractHandler,
registry: () => registry
});
module.exports = __toCommonJS(index_exports);
// packages/smart-contract/package.json
var package_default = {
name: "@m3s/smart-contract",
version: "1.9.2",
type: "module",
description: "A modular toolkit for generating, compiling, deploying, and interacting with Ethereum-compatible smart contracts",
license: "MIT",
keywords: [
"smart-contract",
"ethereum",
"erc20",
"erc721",
"erc1155",
"solidity",
"blockchain",
"web3",
"openzeppelin"
],
repository: {
type: "git",
url: "git@bitbucket.org:ctb-marisca/ms3-package.git",
directory: "packages/smart-contract"
},
main: "./dist/index.cjs.js",
module: "./dist/index.esm.js",
types: "./dist/index.d.ts",
exports: {
".": {
types: "./dist/index.d.ts",
import: "./dist/index.esm.js",
require: "./dist/index.cjs.js"
},
"./package.json": "./package.json"
},
scripts: {
build: "tsc -b",
test: "vitest run --sequence.sequential",
"test:core": "vitest run 01_Core.test.ts 02_IBaseContractHandler.test.ts",
"test:erc20": "vitest run 03_ERC20.test.ts",
"test:erc721": "vitest run 04_ERC721.test.ts",
"test:erc1155": "vitest run 05_ERC1155.test.ts"
},
dependencies: {
"@m3s/wallet": "^2.0.4",
"@openzeppelin/contracts": "^5.2.0",
"@openzeppelin/contracts-upgradeable": "^5.0.0",
"@openzeppelin/wizard": "^0.5.3",
"@openzeppelin/wizard-cairo": "^1.0.0",
"@openzeppelin/wizard-stellar": "^0.1.1",
"@openzeppelin/wizard-stylus": "^0.2.0-alpha.4",
ethers: "^6.13.5",
hardhat: "^2.22.19",
joi: "^17.13.3",
starknet: "^6.24.1"
},
devDependencies: {
"@m3s/common": "*"
},
publishConfig: {
access: "public",
tag: "latest"
},
files: [
"dist",
"README.md"
]
};
// packages/common/dist/errors/AdapterError.js
var 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;
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, this.constructor);
}
}
};
// packages/common/dist/errors/proxy.js
function createErrorHandlingProxy(adapterInstance, 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") {
return async function(...args) {
try {
return await originalValue.apply(target, args);
} catch (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
// Cast as string if WalletErrorCode is an enum
});
}
};
}
return originalValue;
}
});
}
// packages/common/dist/registry/registry.js
function getPropertyByPath(obj, path3) {
return path3.split(".").reduce((currentObject, key) => {
return currentObject && typeof currentObject === "object" && Object.prototype.hasOwnProperty.call(currentObject, key) ? currentObject[key] : void 0;
}, obj);
}
var UniversalRegistry = class {
constructor() {
__publicField(this, "modules", /* @__PURE__ */ new Map());
__publicField(this, "adapters", /* @__PURE__ */ new Map());
__publicField(this, "compatibilityMatrices", /* @__PURE__ */ new Map());
}
/**
* 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) {
const moduleAdapters = this.adapters.get(moduleName);
if (!moduleAdapters)
continue;
const matrix = this.getCompatibilityMatrix(currentAdapter.moduleName, currentAdapter.name, currentAdapter.version);
for (const [, adapterMetadata2] of moduleAdapters) {
if (moduleName === currentAdapter.moduleName && adapterMetadata2.name === currentAdapter.name && adapterMetadata2.version === currentAdapter.version) {
continue;
}
let isCompatible = true;
if (adapterMetadata2.environment && matrix) {
const currentAdapterMeta = this.getAdapter(currentAdapter.moduleName, currentAdapter.name, currentAdapter.version);
if (currentAdapterMeta?.environment) {
const environmentOverlap = currentAdapterMeta.environment.supportedEnvironments.some((env) => adapterMetadata2.environment.supportedEnvironments.includes(env));
if (!environmentOverlap) {
isCompatible = false;
}
}
}
if (matrix && isCompatible) {
const crossModuleCompat = matrix.crossModuleCompatibility.find((cmc) => cmc.moduleName === moduleName);
if (crossModuleCompat) {
const compatibleAdapter = crossModuleCompat.compatibleAdapters.find((ca) => ca.name === adapterMetadata2.name && ca.versions.includes(adapterMetadata2.version));
isCompatible = !!compatibleAdapter;
}
}
if (isCompatible) {
compatibleAdapters.push(adapterMetadata2);
}
}
}
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());
}
/**
* Check if an adapter supports a specific feature/method
*/
supportsFeature(moduleName, name, version, featureName) {
const adapter = this.getAdapter(moduleName, name, version);
if (!adapter)
return false;
return typeof adapter.adapterClass.prototype[featureName] === "function";
}
/**
* Find adapters that support a specific feature across all modules
*/
findAdaptersWithFeature(featureName) {
const result = [];
for (const [moduleName, moduleAdapters] of Array.from(this.adapters.entries())) {
for (const [, metadata] of Array.from(moduleAdapters.entries())) {
if (this.supportsFeature(moduleName, metadata.name, metadata.version, featureName)) {
result.push(metadata);
}
}
}
return result;
}
/**
* 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;
}
/**
* ✅ NEW: Helper methods extracted from devtool.ts
*/
areEnvironmentsCompatible(adapter1, adapter2) {
if (!adapter1.environment || !adapter2.environment)
return true;
return adapter1.environment.supportedEnvironments.some((env) => adapter2.environment.supportedEnvironments.includes(env));
}
areInterfacesCompatible(adapter1, adapter2) {
if (!adapter1.features || !adapter2.features)
return true;
const methods1 = adapter1.features.map((f) => f.name);
const methods2 = adapter2.features.map((f) => f.name);
const coreMethods = ["initialize", "isInitialized"];
return coreMethods.every((method) => methods1.includes(method) && methods2.includes(method));
}
/**
* ✅ NEW: Find all compatible adapters for a given adapter
*/
findCompatibleAdapters(moduleName, adapterName, version) {
const sourceAdapter = this.getAdapter(moduleName, adapterName, version);
if (!sourceAdapter)
return [];
const compatible = [];
for (const module2 of this.getAllModules()) {
if (module2.name === moduleName)
continue;
const moduleAdapters = this.getModuleAdapters(module2.name);
for (const targetAdapter of moduleAdapters) {
const report = this.getCompatibilityReport(moduleName, adapterName, version, module2.name, targetAdapter.name, targetAdapter.version);
if (report.compatible) {
const envScore = this.areEnvironmentsCompatible(sourceAdapter, targetAdapter) ? 1 : 0;
const interfaceScore = this.areInterfacesCompatible(sourceAdapter, targetAdapter) ? 1 : 0;
const compatibility = (envScore + interfaceScore) / 2;
compatible.push({
module: module2.name,
adapter: targetAdapter.name,
version: targetAdapter.version,
compatibility
});
}
}
}
return compatible.sort((a, b) => b.compatibility - a.compatibility);
}
/**
* ✅ NEW: Get detailed compatibility report between adapters
*/
getCompatibilityReport(module1, adapter1, version1, module2, adapter2, version2) {
const metadata1 = this.getAdapter(module1, adapter1, version1);
const metadata2 = this.getAdapter(module2, adapter2, version2);
if (!metadata1 || !metadata2) {
return {
compatible: false,
conflicts: [{
type: "version",
severity: "error",
description: "One or both adapters not found",
affectedVersions: [version1, version2]
}],
recommendations: ["Verify adapter names and versions"],
supportedVersions: []
};
}
const conflicts = [];
let compatible = true;
if (!this.areEnvironmentsCompatible(metadata1, metadata2)) {
compatible = false;
conflicts.push({
type: "environment",
severity: "error",
description: `Environment incompatibility: ${adapter1} requires ${metadata1.environment?.supportedEnvironments.join(", ")}, ${adapter2} requires ${metadata2.environment?.supportedEnvironments.join(", ")}`,
affectedVersions: [version1, version2],
suggestedAction: `Use ${adapter1} in ${metadata1.environment?.supportedEnvironments.join("/")} environment, or ${adapter2} in ${metadata2.environment?.supportedEnvironments.join("/")} environment`
});
}
if (!this.areInterfacesCompatible(metadata1, metadata2)) {
compatible = false;
conflicts.push({
type: "feature",
severity: "error",
description: `Interface incompatibility: Core methods missing or incompatible`,
affectedVersions: [version1, version2],
suggestedAction: "Verify both adapters implement required interface methods"
});
}
const recommendations = [];
if (compatible) {
recommendations.push(`\u2705 ${adapter1}@${version1} and ${adapter2}@${version2} are compatible`);
if (metadata1.environment && metadata2.environment) {
const commonEnvs = metadata1.environment.supportedEnvironments.filter((env) => metadata2.environment.supportedEnvironments.includes(env));
recommendations.push(`\u{1F4A1} Use in ${commonEnvs.join(" or ")} environment${commonEnvs.length > 1 ? "s" : ""}`);
}
} else {
recommendations.push(`\u274C ${adapter1}@${version1} and ${adapter2}@${version2} are not compatible`);
if (conflicts.some((c) => c.type === "environment")) {
const allAdapters = this.getModuleAdapters(module1);
for (const alt of allAdapters) {
if (alt.name !== adapter1 && metadata2.environment && alt.environment?.supportedEnvironments.some((env) => metadata2.environment.supportedEnvironments.includes(env))) {
recommendations.push(`\u{1F4A1} Try ${alt.name}@${alt.version} instead of ${adapter1} for ${metadata2.environment.supportedEnvironments.join("/")} compatibility`);
}
}
}
}
return {
compatible,
conflicts,
recommendations,
supportedVersions: compatible ? [version1, version2] : []
};
}
};
var registry = new UniversalRegistry();
// packages/common/dist/registry/compatibility.js
var WALLET_COMPATIBILITY = {
"ethers@1.0.0": {
adapterName: "ethers",
version: "1.0.0",
compatibleVersions: ["1.0.0"],
breakingChanges: [],
crossModuleCompatibility: [
{
moduleName: "smart-contract",
compatibleAdapters: [
{ name: "openZeppelin", versions: ["1.0.0"] }
]
},
{
moduleName: "crosschain",
compatibleAdapters: [
{ name: "lifi", versions: ["1.0.0"] }
]
}
]
},
"web3auth@1.0.0": {
adapterName: "web3auth",
version: "1.0.0",
compatibleVersions: ["1.0.0"],
breakingChanges: [],
crossModuleCompatibility: [
{
moduleName: "smart-contract",
compatibleAdapters: [
{ name: "openZeppelin", versions: ["1.0.0"] }
]
}
// ❌ NOTE: web3auth is BROWSER-only, so NO crosschain compatibility
// crosschain adapters typically need server environment
]
}
};
var SMART_CONTRACT_COMPATIBILITY = {
"openZeppelin@1.0.0": {
adapterName: "openZeppelin",
version: "1.0.0",
compatibleVersions: ["1.0.0"],
breakingChanges: [],
crossModuleCompatibility: [
{
moduleName: "wallet",
compatibleAdapters: [
{ name: "ethers", versions: ["1.0.0"] },
{ name: "web3auth", versions: ["1.0.0"] }
]
}
]
}
};
var CROSSCHAIN_COMPATIBILITY = {
"lifi@1.0.0": {
adapterName: "lifi",
version: "1.0.0",
compatibleVersions: ["1.0.0"],
breakingChanges: [],
crossModuleCompatibility: [
{
moduleName: "wallet",
compatibleAdapters: [
{ name: "ethers", versions: ["1.0.0"] }
// ❌ NOTE: NO web3auth - environment incompatibility
]
}
]
}
};
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;
}
}
// packages/common/dist/types/registry.js
var Ms3Modules;
(function(Ms3Modules2) {
Ms3Modules2["wallet"] = "wallet";
Ms3Modules2["smartcontract"] = "smart-contract";
Ms3Modules2["crosschain"] = "crosschain";
})(Ms3Modules || (Ms3Modules = {}));
var RuntimeEnvironment;
(function(RuntimeEnvironment2) {
RuntimeEnvironment2["BROWSER"] = "browser";
RuntimeEnvironment2["SERVER"] = "server";
})(RuntimeEnvironment || (RuntimeEnvironment = {}));
// packages/common/dist/types/error.js
var WalletErrorCode;
(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 = {}));
var CrossChainErrorCode;
(function(CrossChainErrorCode2) {
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 = {}));
var SmartContractErrorCode;
(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/common/dist/helpers/network.js
var import_ethers = require("ethers");
var _NetworkHelper = class _NetworkHelper {
constructor() {
__publicField(this, "networkCache");
__publicField(this, "isLoadingNetworks");
__publicField(this, "initializationPromise", null);
this.networkCache = {
// Default entries ensure basic functionality even if API fails
ethereum: { chainId: "0x1", name: "Ethereum Mainnet", rpcUrls: ["https://eth.llamarpc.com", "https://ethereum-rpc.publicnode.com", "https://1rpc.io/eth", "https://cloudflare-eth.com"], blockExplorerUrl: "https://etherscan.io", ticker: "ETH", tickerName: "Ethereum", displayName: "Ethereum Mainnet" },
sepolia: { chainId: "0xaa36a7", name: "Sepolia Testnet", rpcUrls: ["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", ticker: "ETH", tickerName: "Ethereum", displayName: "Sepolia Testnet" },
polygon: { chainId: "0x89", name: "Polygon Mainnet", rpcUrls: ["https://polygon-rpc.com", "https://polygon.llamarpc.com", "https://polygon.drpc.org"], blockExplorerUrl: "https://polygonscan.com", ticker: "MATIC", tickerName: "Polygon", displayName: "Polygon Mainnet" },
arbitrum: { chainId: "0xa4b1", name: "Arbitrum One", rpcUrls: ["https://arb1.arbitrum.io/rpc", "https://arbitrum.llamarpc.com", "https://arbitrum-one.public.blastapi.io"], blockExplorerUrl: "https://arbiscan.io", ticker: "ETH", tickerName: "Ethereum", displayName: "Arbitrum One" },
optimism: { chainId: "0xa", name: "Optimism", rpcUrls: ["https://mainnet.optimism.io", "https://optimism.llamarpc.com", "https://optimism.publicnode.com"], blockExplorerUrl: "https://optimistic.etherscan.io", ticker: "ETH", tickerName: "Ethereum", displayName: "Optimism" }
};
this.isLoadingNetworks = false;
this.initializationPromise = this.loadAllNetworks().then(() => {
}).catch((err) => {
console.error("[NetworkHelper] Background network loading failed:", err.message);
});
}
async loadAllNetworks() {
if (this.isLoadingNetworks) {
if (this.initializationPromise)
await this.initializationPromise;
return this.networkCache;
}
this.isLoadingNetworks = true;
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 15e3);
const response = await fetch("https://chainlist.org/rpcs.json", { signal: controller.signal });
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`Failed to fetch networks: ${response.status} ${response.statusText}`);
}
const networks = await response.json();
for (const network of networks) {
if (!network.chainId)
continue;
const filteredRpcUrls = (network.rpc || []).map((rpc) => typeof rpc === "string" ? rpc : rpc?.url).filter((url) => !!url && (url.startsWith("http://") || url.startsWith("https://")) && !url.includes("/demo") && !/\{\$?.*\}/.test(url) && !/api_key|api-key|apikey/i.test(url) && !url.includes("wss://"));
if (filteredRpcUrls.length === 0)
continue;
const chainIdNum = network.chainId;
const chainIdHex = `0x${chainIdNum.toString(16)}`;
const chainIdDecString = chainIdNum.toString();
const formattedNetwork = {
chainId: chainIdHex,
name: network.name,
displayName: network.name,
rpcUrls: filteredRpcUrls,
// rpcUrls[0] is the primary
ticker: network.nativeCurrency?.symbol || "",
tickerName: network.nativeCurrency?.name || "",
blockExplorerUrl: network.explorers?.[0]?.url || "",
shortName: network.shortName,
chainSlug: network.chainSlug
};
const normalizedName = network.name.toLowerCase().replace(/\s+/g, "");
this.networkCache[normalizedName] = formattedNetwork;
this.networkCache[chainIdDecString] = formattedNetwork;
this.networkCache[chainIdHex.toLowerCase()] = formattedNetwork;
if (network.shortName)
this.networkCache[network.shortName.toLowerCase()] = formattedNetwork;
if (network.chainSlug)
this.networkCache[network.chainSlug] = formattedNetwork;
}
} catch (error) {
console.warn("[NetworkHelper] Failed to load networks from ChainList API, using defaults:", error.message);
} finally {
this.isLoadingNetworks = false;
}
return this.networkCache;
}
/**
* Filters a collection of NetworkConfig | null objects, returning only valid NetworkConfig objects.
* A config is considered valid if it's not null, has a chainId, and has at least one RPC URL.
* @param configs - A Record<string, NetworkConfig | null> or Array<NetworkConfig | null>.
* @returns A collection of the same type (Record or Array) containing only valid NetworkConfig objects.
*/
static filterValidConfigs(configs) {
const isValid = (config) => !!config && !!config.chainId && !!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;
}
}
/**
* Asserts that a given NetworkConfig is valid.
* Throws an error if the config is null, or missing chainId, or rpcUrls.
* @param config - The NetworkConfig | null to validate.
* @param context - Optional context string to include in the error message.
* @returns The validated NetworkConfig (guaranteed to be non-null and valid).
* @throws Error if the config is invalid.
*/
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 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) {
await this.initializationPromise;
}
}
async testRpcConnection(url, expectedChainId, timeoutMs = 5e3) {
try {
const provider = new import_ethers.JsonRpcProvider(url, void 0, { staticNetwork: true });
const networkPromise = provider.getNetwork();
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout connecting to ${url}`)), timeoutMs));
const network = await Promise.race([networkPromise, timeoutPromise]);
await provider.destroy();
const networkChainIdStr = network.chainId.toString();
const expectedChainIdStr = expectedChainId.toString();
const expectedHex = expectedChainIdStr.startsWith("0x") ? expectedChainIdStr.toLowerCase() : `0x${parseInt(expectedChainIdStr, 10).toString(16).toLowerCase()}`;
const expectedDec = expectedChainIdStr.startsWith("0x") ? parseInt(expectedChainIdStr, 16).toString() : expectedChainIdStr;
if (networkChainIdStr !== expectedHex && networkChainIdStr !== expectedDec) {
return false;
}
return true;
} catch (error) {
return false;
}
}
async fetchChainListNetwork(networkIdentifier) {
await this.ensureInitialized();
const identifierStr = String(networkIdentifier).toLowerCase();
let cachedConfig = this.networkCache[identifierStr] || this.networkCache[String(networkIdentifier)];
if (cachedConfig) {
return cachedConfig;
}
if (identifierStr.includes("arbi")) {
cachedConfig = this.networkCache.arbitrum || this.networkCache.arbitrumone;
if (cachedConfig)
return cachedConfig;
}
if (identifierStr.includes("opti")) {
cachedConfig = this.networkCache.optimism;
if (cachedConfig)
return cachedConfig;
}
if (identifierStr === "sepolia" || identifierStr === "11155111" || identifierStr === "0xaa36a7") {
return this.networkCache.sepolia || null;
}
return null;
}
async getNetworkConfig(networkIdentifier, preferredRpcUrls = [], useOnlyPreferredRpc = false) {
await this.ensureInitialized();
const baseConfig = await this.fetchChainListNetwork(String(networkIdentifier));
if (!baseConfig || !baseConfig.chainId || !baseConfig.rpcUrls || baseConfig.rpcUrls.length === 0) {
return null;
}
const uniquePreferred = [...new Set(preferredRpcUrls.filter((url) => url))];
let urlsToTest = [];
let foundInPreferred = false;
if (uniquePreferred.length > 0) {
urlsToTest.push(...uniquePreferred);
}
if (!useOnlyPreferredRpc) {
const baseRpcUrlsFromCache = (Array.isArray(baseConfig.rpcUrls) ? baseConfig.rpcUrls : []).filter((url) => !uniquePreferred.includes(url));
urlsToTest.push(...baseRpcUrlsFromCache);
} else if (uniquePreferred.length === 0) {
console.warn(`[NetworkHelper] getNetworkConfig called with useOnlyPreferredRpc=true but no preferredRpcUrls were provided for ${networkIdentifier}.`);
return null;
}
if (urlsToTest.length === 0) {
return null;
}
let workingUrl = null;
for (const url of urlsToTest) {
if (await this.testRpcConnection(url, baseConfig.chainId)) {
workingUrl = url;
if (uniquePreferred.includes(url)) {
foundInPreferred = true;
}
break;
}
}
if (!workingUrl) {
return null;
}
if (!useOnlyPreferredRpc && uniquePreferred.length > 0 && !foundInPreferred) {
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,
blockExplorerUrl: baseConfig.blockExplorerUrl,
ticker: baseConfig.ticker,
tickerName: baseConfig.tickerName,
shortName: baseConfig.shortName,
chainSlug: baseConfig.chainSlug
};
}
/**
* Try each URL until one returns a matching chainId within timeout.
* @returns the first working RPC, or null if none worked.
*/
async findFirstWorkingRpc(urls, expectedChainId, timeoutMs = 3e3) {
for (const url of urls) {
try {
const ok = await this.testRpcConnection(url, expectedChainId, timeoutMs);
if (ok)
return url;
} catch {
}
}
return null;
}
};
__publicField(_NetworkHelper, "instance");
var NetworkHelper = _NetworkHelper;
// packages/common/dist/helpers/keys.js
var import_ethers2 = require("ethers");
var PrivateKeyHelper = class {
/**
* Generates a new random EVM-compatible private key.
* @returns A string representing the private key (hexadecimal, 0x-prefixed).
*/
generatePrivateKey() {
try {
const wallet = import_ethers2.Wallet.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 import_ethers2.Wallet(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 import_ethers2.Wallet.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 import_ethers2.Wallet(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 = import_ethers2.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, path3) {
const hdPath = path3 || "m/44'/60'/0'/0/0";
try {
if (!import_ethers2.Mnemonic.isValidMnemonic(mnemonic)) {
throw new Error("Invalid mnemonic phrase provided.");
}
const mnemonicInstance = import_ethers2.Mnemonic.fromPhrase(mnemonic);
const hdNode = import_ethers2.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" && (0, import_ethers2.isHexString)(privateKey, 32);
}
};
// packages/common/dist/helpers/validator.js
function validateAdapterParameters(args) {
const { moduleName, name, version, params, adapterInfo, registry: registry2, factoryMethodName } = args;
const { neededFeature } = params;
if (neededFeature && typeof neededFeature === "string") {
if (!registry2.supportsFeature(moduleName, name, version, neededFeature)) {
throw new AdapterError(`Feature '${neededFeature}' is not supported by adapter '${name}' for module '${moduleName}'.`, {
methodName: factoryMethodName,
code: "FEATURE_NOT_SUPPORTED",
details: { feature: neededFeature }
});
}
} else if (neededFeature && !Array.isArray(neededFeature) && typeof neededFeature !== "string") {
console.warn(`[validateAdapterParameters] 'neededFeature' for ${name} is of an unexpected type: ${typeof neededFeature}. It should typically be a string.`);
}
if (adapterInfo.requirements && adapterInfo.requirements.length > 0) {
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.type) {
const errorMessage = req.message || `Required option '${req.path}' for adapter '${name}' must be of type '${req.type}', but received '${valueType}'.`;
throw new AdapterError(errorMessage, {
methodName: factoryMethodName,
code: "INVALID_ADAPTER_REQUIREMENT_TYPE",
details: { path: req.path, message: req.message, expectedType: req.type, actualType: valueType }
});
}
}
}
}
}
// packages/common/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}`);
});
}
}
// packages/common/dist/helpers/devtool.js
function analyzeJoiSchema(schema, basePath) {
console.log(`\u{1F52C} [analyzeJoiSchema] Analyzing schema at path: ${basePath}`);
const requirements = [];
try {
const description = schema.describe();
console.log(`\u{1F4CB} [analyzeJoiSchema] Schema description type:`, description.type);
console.log(`\u{1F4CB} [analyzeJoiSchema] Schema keys:`, description.keys ? Object.keys(description.keys) : "NO KEYS");
if (description.type === "object" && description.keys) {
console.log(`\u2705 [analyzeJoiSchema] Processing object schema with ${Object.keys(description.keys).length} keys`);
for (const [key, fieldDesc] of Object.entries(description.keys)) {
console.log(`\u{1F511} [analyzeJoiSchema] Processing field: ${key}`);
console.log(`\u{1F4DD} [analyzeJoiSchema] Field description:`, fieldDesc);
const fieldSchema = fieldDesc;
const fieldPath = `${basePath}.${key}`;
const hasPresenceFlag = fieldSchema.flags?.presence;
const isRequired = hasPresenceFlag === "required" || !hasPresenceFlag && !fieldSchema.flags?.optional;
let fieldType = fieldSchema.type || "any";
if (fieldType === "alternatives" && fieldSchema.matches) {
fieldType = fieldSchema.matches[0]?.schema?.type || "any";
}
let message = fieldSchema.flags?.description || "";
if (!message) {
const mandatory = isRequired ? "required" : "optional";
message = `${key} is ${mandatory} and must be of type: ${fieldType}`;
}
console.log(`\u{1F4CA} [analyzeJoiSchema] Field ${key}: type=${fieldType}, required=${isRequired}, message="${message}"`);
requirements.push({
path: fieldPath,
type: fieldType,
allowUndefined: !isRequired,
message
});
if (fieldSchema.type === "object" && fieldSchema.keys) {
console.log(`\u{1F504} [analyzeJoiSchema] Recursing into nested object: ${key}`);
const nestedRequirements = analyzeJoiSchemaFromDescription(fieldSchema, fieldPath);
requirements.push(...nestedRequirements);
}
}
} else {
console.warn(`\u26A0\uFE0F [analyzeJoiSchema] Expected object schema but got type: ${description.type}`);
}
} catch (error) {
console.error(`\u274C [analyzeJoiSchema] Failed to analyze schema at ${basePath}:`, error);
}
console.log(`\u{1F4CA} [analyzeJoiSchema] Generated ${requir