feat:contract deployment for an IBFT private network

This commit is contained in:
Ricky Putra Pratama Tedjo 2025-08-07 15:21:46 +07:00
parent 228b06f4c0
commit f6fca94cae
6 changed files with 134 additions and 7 deletions

View File

@ -1,6 +1,24 @@
import { Controller } from "@nestjs/common";
import { Body, Controller, Get, Post } from "@nestjs/common";
import { DeployerService } from "../services";
import { ConfigService } from "@nestjs/config";
import { DeployerDto } from "../dtos";
@Controller()
@Controller('contract')
export class DeployerController {
// Controller methods go here
constructor(
private readonly service: DeployerService,
private readonly config: ConfigService,
){}
@Post()
async createContract(@Body() dto: DeployerDto) {
return this.service.createContract(dto);
}
@Get()
async getContracts(){
return this.service.getContracts();
}
}

View File

@ -1,9 +1,11 @@
import { Module } from "@nestjs/common";
import { DeployerController } from "./controllers";
import { DeployerService } from "./services";
@Module({
imports: [],
controllers: [],
providers: [],
controllers: [DeployerController],
providers: [DeployerService],
exports: [],
})
export class DeployerModule {}

View File

@ -0,0 +1,9 @@
import { Transform } from "class-transformer";
import { IsNotEmpty, IsString } from "class-validator";
export class DeployerDto {
@IsNotEmpty({ message: 'Contract name is required' })
@IsString({ message: 'Contract name must be a string' })
@Transform(({ value }) => value.toString())
contractName: string;
}

View File

@ -0,0 +1 @@
export * from './deployer.dto';

View File

@ -1,6 +1,102 @@
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { ProviderService } from "src/common/utils";
import { PostgresService } from "src/core/psql/postgres.service";
import { DeployerDto } from "../dtos";
import { ethers } from "ethers";
import { Contract } from "../types";
@Injectable()
export class DeployerService {
// Service methods go here
constructor(
private readonly config: ConfigService,
private readonly db: PostgresService,
private readonly provider: ProviderService
){}
async createContract(dto: DeployerDto) {
try{
const { provider, wallet } = await this.provider.getProviderAndWallet();
if (!provider || !wallet) {
throw new Error('Provider or wallet not initialized');
}
const {abi, bytecode} = await this.provider.getAbiAndBytecode();
if (!abi) {
throw new Error('ABI not found');
}
const contract = new ethers.ContractFactory(
abi,
bytecode,
wallet
);
const contractInstance = await contract.deploy( dto.contractName ,{
value: ethers.toBigInt(0),
maxFeePerGas: 1000n,
maxPriorityFeePerGas: 0n,
gasLimit: 3_000_000,
chainId: (await provider.getNetwork()).chainId,
});
await contractInstance.waitForDeployment();
const deployedAddress = await contractInstance.getAddress();
const contractData: Contract = {
contractaddress: deployedAddress,
useraddress: wallet.address.toLowerCase(),
}
await this.db.insert<Contract>('contracts', contractData);
return {
status: 'success',
message: 'Contract created successfully at address: ' + deployedAddress,
};
} catch (error) {
return {
statusCode: error.statusCode,
message: error.message || 'Contract creation failed',
};
}
}
async getContracts() {
const { provider, wallet } = await this.provider.getProviderAndWallet();
if (!provider || !wallet) {
throw new Error('Provider or wallet not initialized');
}
const contractList = await this.db.getAll<Contract>('contracts', {
useraddress: wallet.address.toLowerCase(),
});
if (contractList.length === 0) {
return 'No contracts found';
}
const { abi } = await this.provider.getAbiAndBytecode();
if (!abi) {
throw new Error('ABI not found');
}
const contractsWithTx = await Promise.all(contractList.map(async contract => {
const contractInstance = new ethers.Contract(contract.contractaddress, abi, provider);
let contractName = '';
try {
contractName = await contractInstance.getName();
} catch (err) {
contractName = 'Unknown';
}
return {
contractAddress: contract.contractaddress,
contractName,
contractBalance: (await provider.getBalance(contract.contractaddress)).toString()
};
}));
return contractsWithTx;
}
}

View File

@ -1,6 +1,7 @@
import { Module } from "@nestjs/common";
import { DeployerModule } from "./deployer/deployer.module";
@Module({
imports: []
imports: [DeployerModule]
})
export class ModulesModule {}