dop-stick
Version:
Source control tooling for versionable-upgradeable smart contracts
145 lines • 6.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LibraryManager = void 0;
const ethers_1 = require("ethers");
const libraryTimelineAdapter_1 = require("../logsAndMetrics/adapters/libraryTimelineAdapter");
class LibraryManager {
constructor(provider, signer, libraries) {
this.deployedLibraries = new Map();
this.libraryConfigs = new Map();
this.provider = provider;
this.signer = signer;
this.timeline = new libraryTimelineAdapter_1.LibraryTimelineAdapter();
if (libraries) {
Object.entries(libraries).forEach(([name, config]) => {
this.libraryConfigs.set(name, config);
});
}
}
async resolveLibraries(requiredLibraries) {
this.timeline.startLibraryResolution(requiredLibraries);
const resolved = {};
for (const libName of requiredLibraries) {
try {
const libAddress = await this.resolveLibrary(libName);
resolved[libName] = libAddress;
this.timeline.logLibraryResolved(libName, libAddress);
}
catch (error) {
this.timeline.logLibraryError(libName, error);
throw error;
}
}
return resolved;
}
async resolveLibrary(name) {
var _a;
// Return if already deployed
if (this.deployedLibraries.has(name)) {
return this.deployedLibraries.get(name);
}
const config = this.libraryConfigs.get(name);
if (!config) {
throw new Error(`Library configuration not found for: ${name}`);
}
// If address is provided, verify it
if (config.address) {
const code = await this.provider.getCode(config.address);
if (code !== '0x') {
this.deployedLibraries.set(name, config.address);
return config.address;
}
}
// Deploy dependencies first
if ((_a = config.dependencies) === null || _a === void 0 ? void 0 : _a.length) {
this.timeline.logDependencyResolution(name, config.dependencies);
await Promise.all(config.dependencies.map(dep => this.resolveLibrary(dep)));
}
// Deploy the library
return await this.deployLibrary(config);
}
async deployLibrary(config) {
var _a;
if (!config.bytecode || !config.abi) {
throw new Error(`Missing bytecode or ABI for library: ${config.name}`);
}
this.timeline.logLibraryDeployment(config.name, 'starting');
try {
// Replace library references in bytecode if needed
let processedBytecode = config.bytecode;
if ((_a = config.dependencies) === null || _a === void 0 ? void 0 : _a.length) {
for (const dep of config.dependencies) {
const depAddress = this.deployedLibraries.get(dep);
if (!depAddress) {
throw new Error(`Dependency not deployed: ${dep}`);
}
processedBytecode = this.linkLibrary(processedBytecode, dep, depAddress);
}
}
// Deploy
const factory = new ethers_1.ethers.ContractFactory(config.abi, processedBytecode, this.signer);
const library = await factory.deploy();
await library.deployed();
this.deployedLibraries.set(config.name, library.address);
this.timeline.logLibraryDeployment(config.name, 'success', library.address);
return library.address;
}
catch (error) {
this.timeline.logLibraryDeployment(config.name, 'failed', undefined, error);
throw error;
}
}
linkLibrary(bytecode, libName, libAddress) {
const placeholder = `__$${ethers_1.ethers.utils.solidityKeccak256(['string'], [libName]).slice(2, 36)}$__`;
const regex = new RegExp(placeholder, 'g');
return bytecode.replace(regex, libAddress.slice(2));
}
/**
* Deploy a library using a specific wallet
* @param lib Library reference to deploy
* @param wallet Wallet to use for deployment
* @returns Promise<LibraryDeploymentResult>
*/
async deployLibraryWithWallet(lib, wallet) {
var _a;
const config = this.libraryConfigs.get(lib.name);
if (!config) {
throw new Error(`Library configuration not found for: ${lib.name}`);
}
if (!config.bytecode || !config.abi) {
throw new Error(`Missing bytecode or ABI for library: ${lib.name}`);
}
this.timeline.logLibraryDeployment(lib.name, 'starting');
try {
// Replace library references in bytecode if needed
let processedBytecode = config.bytecode;
if ((_a = config.dependencies) === null || _a === void 0 ? void 0 : _a.length) {
for (const dep of config.dependencies) {
const depAddress = this.deployedLibraries.get(dep);
if (!depAddress) {
throw new Error(`Dependency not deployed: ${dep}`);
}
processedBytecode = this.linkLibrary(processedBytecode, dep, depAddress);
}
}
// Deploy using provided wallet
const factory = new ethers_1.ethers.ContractFactory(config.abi, processedBytecode, wallet);
const library = await factory.deploy();
const deployedLibrary = await library.deployed();
const result = {
name: lib.name,
address: deployedLibrary.address,
deploymentHash: library.deployTransaction.hash
};
this.deployedLibraries.set(lib.name, result.address);
this.timeline.logLibraryDeployment(lib.name, 'success', result.address);
return result;
}
catch (error) {
this.timeline.logLibraryDeployment(lib.name, 'failed', undefined, error);
throw error;
}
}
}
exports.LibraryManager = LibraryManager;
//# sourceMappingURL=libraryManager.js.map