multisig fully ready + salaries almost ready.

refactor contracts and refactor structure of app.
swagger update
This commit is contained in:
emochka2007 2024-05-13 02:12:50 +03:00
parent ed2f6b9eca
commit 9ec370c8f6
34 changed files with 502 additions and 325 deletions

View File

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ContractFactoryModule } from './contract-factory/contract-factory.module';
import { ContractInteractModule } from './contract-interact/contract-interact.module';
import { ConfigModule } from '@nestjs/config';
@ -10,7 +10,6 @@ import { ConfigModule } from '@nestjs/config';
ConfigModule.forRoot({
isGlobal: true,
}),
ContractFactoryModule,
ContractInteractModule,
],
controllers: [AppController],

View File

@ -1,20 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ContractFactoryController } from './contract-factory.controller';
import { ContractFactoryService } from './contract-factory.service';
describe('ContractFactoryController', () => {
let controller: ContractFactoryController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ContractFactoryController],
providers: [ContractFactoryService],
}).compile();
controller = module.get<ContractFactoryController>(ContractFactoryController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -1,26 +0,0 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
} from '@nestjs/common';
import { ContractFactoryService } from './contract-factory.service';
import { CreateContractFactoryDto } from './dto/create-contract-factory.dto';
import { UpdateContractFactoryDto } from './dto/update-contract-factory.dto';
import { ApiTags } from '@nestjs/swagger';
import { MultiSigWalletDto } from 'src/hardhat/modules/dto/multi-sig.dto';
@ApiTags('contract-factory')
@Controller('contract-factory')
export class ContractFactoryController {
constructor(
private readonly contractFactoryService: ContractFactoryService,
) {}
@Post('multi-sig')
create(@Body() createContractFactoryDto: MultiSigWalletDto) {
return this.contractFactoryService.createMultiSig(createContractFactoryDto);
}
}

View File

@ -1,11 +0,0 @@
import { HardhatModule } from '../hardhat/modules/hardhat.module';
import { Module } from '@nestjs/common';
import { ContractFactoryService } from './contract-factory.service';
import { ContractFactoryController } from './contract-factory.controller';
@Module({
imports: [HardhatModule],
controllers: [ContractFactoryController],
providers: [ContractFactoryService],
})
export class ContractFactoryModule {}

View File

@ -1,18 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ContractFactoryService } from './contract-factory.service';
describe('ContractFactoryService', () => {
let service: ContractFactoryService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ContractFactoryService],
}).compile();
service = module.get<ContractFactoryService>(ContractFactoryService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -1,21 +0,0 @@
import { HardhatService } from '../hardhat/modules/hardhat.service';
import { Injectable } from '@nestjs/common';
import { CreateContractFactoryDto } from './dto/create-contract-factory.dto';
import { SalariesService } from 'src/hardhat/modules/salary.service';
import { MultiSigWalletService } from 'src/hardhat/modules/multi-sig/multi-sig.service';
import { MultiSigWalletDto } from 'src/hardhat/modules/dto/multi-sig.dto';
@Injectable()
export class ContractFactoryService {
constructor(
private readonly salaryService: SalariesService,
private readonly multiSigService: MultiSigWalletService,
) {}
async createSalary(createContractFactoryDto: CreateContractFactoryDto) {
return await this.salaryService.deploy();
}
async createMultiSig(dto: MultiSigWalletDto) {
return await this.multiSigService.deploy(dto);
}
}

View File

@ -1,12 +0,0 @@
import { ApiProperty } from '@nestjs/swagger';
export enum ContractType {
SALARY,
AGREEMENT,
}
export class CreateContractFactoryDto {
@ApiProperty({
enum: ContractType,
})
contractType: ContractType;
}

View File

@ -1,4 +0,0 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateContractFactoryDto } from './create-contract-factory.dto';
export class UpdateContractFactoryDto extends PartialType(CreateContractFactoryDto) {}

View File

@ -1,20 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ContractInteractController } from './contract-interact.controller';
import { ContractInteractService } from './contract-interact.service';
describe('ContractInteractController', () => {
let controller: ContractInteractController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ContractInteractController],
providers: [ContractInteractService],
}).compile();
controller = module.get<ContractInteractController>(ContractInteractController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -1,12 +1,9 @@
import { Module } from '@nestjs/common';
import { ContractInteractService } from './contract-interact.service';
import { HardhatModule } from 'src/hardhat/modules/hardhat.module';
import { MultiSigInteractController } from './multi-sig-interact.controller';
@Module({
imports: [HardhatModule],
controllers: [MultiSigInteractController],
providers: [ContractInteractService],
controllers: [],
providers: [],
})
export class ContractInteractModule {}

View File

@ -1,18 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ContractInteractService } from './contract-interact.service';
describe('ContractInteractService', () => {
let service: ContractInteractService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ContractInteractService],
}).compile();
service = module.get<ContractInteractService>(ContractInteractService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -1,26 +0,0 @@
import { Injectable } from '@nestjs/common';
import { CreateContractInteractDto } from './dto/create-contract-interact.dto';
import { UpdateContractInteractDto } from './dto/update-contract-interact.dto';
@Injectable()
export class ContractInteractService {
create(createContractInteractDto: CreateContractInteractDto) {
return 'This action adds a new contractInteract';
}
findAll() {
return `This action returns all contractInteract`;
}
findOne(id: number) {
return `This action returns a #${id} contractInteract`;
}
update(id: number, updateContractInteractDto: UpdateContractInteractDto) {
return `This action updates a #${id} contractInteract`;
}
remove(id: number) {
return `This action removes a #${id} contractInteract`;
}
}

View File

@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
import { IsNumber, IsOptional, IsString } from 'class-validator';
export class SubmitTransactionDto {
@IsString()
@ -16,3 +16,29 @@ export class SubmitTransactionDto {
// @ApiProperty()
data: string;
}
export class ConfirmTransactionDto {
@IsString()
@ApiProperty()
contractAddress: string;
@ApiProperty()
@IsNumber()
index: number;
}
export class ExecuteTransactionDto extends ConfirmTransactionDto {}
export class RevokeConfirmationDto extends ConfirmTransactionDto {}
export class GetTransactionCount {}
export class GetTransactionDto extends ConfirmTransactionDto {}
export class DepositMultiSigDto {
@IsString()
@ApiProperty()
contractAddress: string;
@IsString()
@ApiProperty()
value: string;
}

View File

@ -0,0 +1,10 @@
import { TransactionReceipt, ethers } from 'ethers';
export const parseLogs = (
txReceipt: TransactionReceipt,
contract: ethers.Contract,
) => {
return txReceipt.logs
.map((log) => contract.interface.parseLog(log))
.find((log) => !!log);
};

View File

@ -1,20 +0,0 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { MultiSigWalletService } from 'src/hardhat/modules/multi-sig/multi-sig.service';
import { SubmitTransactionDto } from './dto/multi-sig.dto';
@ApiTags('multi-sig-interact')
@Controller()
export class MultiSigInteractController {
constructor(private readonly multiSigWalletService: MultiSigWalletService) {}
@Get('owners/:address')
async getOwners(@Param('address') address: string) {
return this.multiSigWalletService.getOwners(address);
}
@ApiOkResponse()
@Post('submit-transaction')
async submitTransaction(@Body() dto: SubmitTransactionDto) {
return this.multiSigWalletService.submitTransaction(dto);
}
}

View File

@ -0,0 +1,33 @@
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { error } from 'console';
import { Request, Response } from 'express';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
// constructor(private readonly httpAdapterHost: HttpAdapterHost) {}
catch(exception: any, host: ArgumentsHost): void {
console.log('🚀 ~ AllExceptionsFilter ~ exception:', exception);
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const httpStatus =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const responseBody = {
statusCode: httpStatus,
error: exception?.info?.error.message || exception.toString(),
timestamp: new Date().toISOString(),
};
response.status(500).json(responseBody);
}
}

View File

@ -0,0 +1,10 @@
//
/**
License
sender
receiver
*/

View File

@ -9,6 +9,7 @@ contract Salaries {
address public multisigWallet;
mapping(address => uint) public salaries;
//0xF0d50568e3A7e8259E16663972b11910F89BD8e7
constructor(address _multisigWallet, address _priceFeedAddress) {
multisigWallet = _multisigWallet;
dataFeed = AggregatorV3Interface(_priceFeedAddress);
@ -19,6 +20,10 @@ contract Salaries {
_;
}
function getSalary(address employee) public view returns(uint) {
return salaries[employee];
}
function getLatestUSDTPriceInETH() public view returns (int) {
(
,

View File

@ -1,17 +0,0 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
const JAN_1ST_2030 = 1893456000;
const ONE_GWEI: bigint = 1_000_000_000n;
const LockModule = buildModule("LockModule", (m) => {
const unlockTime = m.getParameter("unlockTime", JAN_1ST_2030);
const lockedAmount = m.getParameter("lockedAmount", ONE_GWEI);
const lock = m.contract("Lock", [unlockTime], {
value: lockedAmount,
});
return { lock };
});
export default LockModule;

View File

@ -1,17 +0,0 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
const JAN_1ST_2030 = 1893456000;
const ONE_GWEI: bigint = 1_000_000_000n;
const owners = ["0xfE87F7EF2a58a1f363a444332df6c131C683e35f"];
const MultiSigModule = buildModule("MultiSigWallet", (m) => {
const ownerP = m.getParameter("owners", owners);
const confirmationsP = m.getParameter("_numConfirmationsRequired", 1);
const deploy = m.contract("MultiSigWallet", [ownerP, confirmationsP]);
return { deploy };
});
export default MultiSigModule;

View File

@ -1,11 +0,0 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
//npx hardhat ignition deploy ignition/modules/Salaries.ts --network amoy
//SalariesModule#Salaries - 0xac45e95Dd5C7F9B1a6C3e4883d04952B9C974b05
const SalariesModule = buildModule("SalariesModule", (m) => {
const salaryContract = m.contract("Salaries");
const answer = m.call(salaryContract, "getChainlinkDataFeedLatestAnswer", []);
console.log("🚀 ~ SalariesModule ~ answer:", answer);
return { salaryContract };
});
export default SalariesModule;

View File

@ -4,9 +4,6 @@ import { ProviderService } from 'src/provider/provider.service';
@Injectable()
export abstract class BaseContractService {
constructor(
public readonly configService: ConfigService,
public readonly providerService: ProviderService,
) {}
constructor(public readonly providerService: ProviderService) {}
abstract deploy(dto: object): Promise<any>;
}

View File

@ -0,0 +1,60 @@
import { ethers } from 'ethers';
// Define a TypeScript type for the EventLog based on the provided structure
export type TransactionLogs = {
provider: ethers.JsonRpcApiProvider;
transactionHash: string;
blockHash: string;
blockNumber: number;
removed: boolean | undefined;
address: string;
data: string;
topics: string[];
index: number;
transactionIndex: number;
interface: Interface;
fragment: EventFragment;
};
type Interface = {
fragments: Fragment[];
deploy: ConstructorFragment[];
fallback: any | null;
receive: boolean;
};
type Fragment = {};
type ConstructorFragment = {};
type EventFragment = {
type: string;
inputs: any[];
name: string;
anonymous: boolean;
};
type SubmitArgs = {
args: [
owner: string,
txIndex: bigint,
to: string,
value: bigint,
data: string,
];
};
type ConfirmArgs = {
args: [owner: string, txIndex: bigint];
};
type ExecuteArgs = {
args: [owner: string, txIndex: bigint];
};
type DepositArgs = {
args: [owner: string, value: bigint, address: string];
};
export type SubmitTransactionLogs = TransactionLogs & SubmitArgs;
export type ConfirmTransactionLogs = TransactionLogs & ConfirmArgs;
export type ExecuteTransactionLogs = TransactionLogs & ExecuteArgs;
export type DepositLogs = TransactionLogs & DepositArgs;

View File

@ -1,15 +1,13 @@
import { Module } from '@nestjs/common';
import { HardhatService } from './hardhat.service';
import { ProviderModule } from 'src/provider/provider.module';
import { MultiSigWalletService } from './multi-sig/multi-sig.service';
import { SalariesService } from './salary.service';
import { BaseContractService } from './base-contract.service';
import { MultiSigModule } from './multi-sig/multi-sig.module';
import { SalariesModule } from './salaries/salaries.module';
@Module({
imports: [ProviderModule, MultiSigModule],
imports: [ProviderModule, MultiSigModule, SalariesModule],
controllers: [],
providers: [HardhatService, SalariesService],
exports: [HardhatService, SalariesService, MultiSigModule],
providers: [HardhatService],
exports: [HardhatService, MultiSigModule, SalariesModule],
})
export class HardhatModule {}

View File

@ -0,0 +1,65 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { MultiSigWalletService } from 'src/hardhat/modules/multi-sig/multi-sig.service';
import {
ConfirmTransactionDto,
DepositMultiSigDto,
ExecuteTransactionDto,
GetTransactionDto,
RevokeConfirmationDto,
SubmitTransactionDto,
} from '../../../contract-interact/dto/multi-sig.dto';
import { MultiSigWalletDto } from './multi-sig.dto';
@ApiTags('multi-sig')
@Controller('multi-sig')
export class MultiSigInteractController {
constructor(private readonly multiSigWalletService: MultiSigWalletService) {}
@Post('deploy')
async deploy(@Body() dto: MultiSigWalletDto) {
return this.multiSigWalletService.deploy(dto);
}
@Get('owners/:address')
async getOwners(@Param('address') address: string) {
return this.multiSigWalletService.getOwners(address);
}
@ApiOkResponse()
@Post('submit-transaction')
async submitTransaction(@Body() dto: SubmitTransactionDto) {
return this.multiSigWalletService.submitTransaction(dto);
}
@ApiOkResponse()
@Post('confirm-transaction')
async confirmTransaction(@Body() dto: ConfirmTransactionDto) {
return this.multiSigWalletService.confirmTransaction(dto);
}
@ApiOkResponse()
@Post('execute-transaction')
async executeTransaction(@Body() dto: ExecuteTransactionDto) {
return this.multiSigWalletService.executeTransaction(dto);
}
@ApiOkResponse()
@Post('revoke-confirmation')
async revokeConfirmation(@Body() dto: RevokeConfirmationDto) {
return this.multiSigWalletService.revokeConfirmation(dto);
}
@Get('transaction-count/:contractAddress')
async getTransactionCount(@Param('contractAddress') contractAddress: string) {
return this.multiSigWalletService.getTransactionCount(contractAddress);
}
@Get('transaction')
async getTransaction(@Body() dto: GetTransactionDto) {
return this.multiSigWalletService.getTransaction(dto);
}
@Post('deposit')
async deposit(@Body() dto: DepositMultiSigDto) {
return this.multiSigWalletService.deposit(dto);
}
}

View File

@ -5,10 +5,11 @@ import { ProviderModule } from 'src/provider/provider.module';
import { BaseContractService } from '../base-contract.service';
import { ProviderService } from 'src/provider/provider.service';
import { MultiSigWalletService } from './multi-sig.service';
import { MultiSigInteractController } from './multi-sig-interact.controller';
@Module({
imports: [ProviderModule],
controllers: [],
controllers: [MultiSigInteractController],
providers: [MultiSigWalletService],
exports: [MultiSigWalletService],
})

View File

@ -1,11 +1,23 @@
import { MultiSigWallet } from '../../typechain-types/contracts/MultiSigWallet';
import { Injectable } from '@nestjs/common';
import { ethers } from 'ethers';
import { TransactionReceipt, ethers } from 'ethers';
import { ConfigService } from '@nestjs/config';
import * as hre from 'hardhat';
import { BaseContractService } from '../base-contract.service';
import { MultiSigWalletDto } from '../dto/multi-sig.dto';
import { SubmitTransactionDto } from 'src/contract-interact/dto/multi-sig.dto';
import { MultiSigWalletDto } from './multi-sig.dto';
import {
ConfirmTransactionDto,
DepositMultiSigDto,
ExecuteTransactionDto,
GetTransactionDto,
RevokeConfirmationDto,
SubmitTransactionDto,
} from 'src/contract-interact/dto/multi-sig.dto';
import {
ConfirmTransactionLogs,
DepositLogs,
ExecuteTransactionLogs,
SubmitTransactionLogs,
} from 'src/hardhat/modules/dto/ethers.dto';
import { parseLogs } from 'src/contract-interact/ethers.helpers';
export class MultiSigWalletService extends BaseContractService {
async deploy(dto: MultiSigWalletDto) {
@ -21,13 +33,8 @@ export class MultiSigWalletService extends BaseContractService {
dto.confirmations,
);
await myContract.waitForDeployment();
console.log(
'🚀 ~ HardhatService ~ deploySalaryContract ~ myContract:',
myContract,
);
const address = myContract.getAddress();
console.log('🚀 ~ SalariesService ~ deploy ~ address:', address);
return address;
}
async getOwners(address: string) {
@ -46,23 +53,119 @@ export class MultiSigWalletService extends BaseContractService {
async submitTransaction(dto: SubmitTransactionDto) {
const { destination, value, data, contractAddress } = dto;
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const multiSigContract = new ethers.Contract(contractAddress, abi);
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
console.log(
'🚀 ~ MultiSigWalletService ~ submitTransaction ~ contract:',
contract.interface,
);
const tx = await contract.submitTransaction(
destination,
value,
new TextEncoder().encode(data),
);
console.log('🚀 ~ MultiSigWalletService ~ submitTransaction ~ tx:', tx);
const tx = await contract.submitTransaction(destination, value, data);
const txResponse: TransactionReceipt = await tx.wait();
const eventParse = parseLogs(txResponse, contract);
return {
txHash: txResponse.hash,
sender: eventParse.args[0].toString(),
txIndex: eventParse.args[1].toString(),
to: eventParse.args[2].toString(),
value: eventParse.args[3].toString(),
data: eventParse.args[4].toString(),
};
}
async confirmTransaction(dto: ConfirmTransactionDto) {
const { contractAddress, index } = dto;
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const tx = await contract.confirmTransaction(index);
const txResponse: TransactionReceipt = await tx.wait();
const eventParse = parseLogs(txResponse, contract);
return {
txHash: txResponse.hash,
sender: eventParse.args[0].toString(),
txIndex: eventParse.args[1].toString(),
};
}
async executeTransaction(dto: ExecuteTransactionDto) {
const { index, contractAddress } = dto;
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const tx = await contract.executeTransaction(index);
const txResponse: TransactionReceipt = await tx.wait();
const eventParse = parseLogs(txResponse, contract);
return {
txHash: txResponse.hash,
sender: eventParse.args[0].toString(),
txIndex: eventParse.args[1].toString(),
};
}
async revokeConfirmation(dto: RevokeConfirmationDto) {
const { index, contractAddress } = dto;
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const tx = await contract.revokeConfirmation(index);
return tx;
}
async getTransactionCount(contractAddress: string) {
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const txCount = await contract.getTransactionCount();
return txCount;
}
async getTransaction(dto: GetTransactionDto) {
const { index, contractAddress } = dto;
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const tx = await contract.getTransaction(index);
return tx;
}
async deposit(dto: DepositMultiSigDto) {
const { contractAddress, value } = dto;
const signer = await this.providerService.getSigner();
const { abi } = await hre.artifacts.readArtifact('MultiSigWallet');
const contract = new ethers.Contract(contractAddress, abi, signer);
const tx = await signer.sendTransaction({
to: contractAddress,
value: BigInt(value),
});
const txResponse: TransactionReceipt = await tx.wait();
const eventParse = parseLogs(txResponse, contract);
return {
txHash: txResponse.hash,
sender: eventParse.args[0].toString(),
value: eventParse.args[1].toString(),
contractBalance: eventParse.args[2].toString(),
};
}
}

View File

@ -0,0 +1,33 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { SalariesService } from './salaries.service';
import {
GetEmployeeSalariesDto,
SalariesDeployDto,
SetSalaryDto,
} from './salaries.dto';
import { ApiTags } from '@nestjs/swagger';
@ApiTags('salaries')
@Controller('salaries')
export class SalariesController {
constructor(private readonly salariesService: SalariesService) {}
@Post('deploy')
async deploy(@Body() dto: SalariesDeployDto) {
return this.salariesService.deploy(dto);
}
@Get('usdt-price/:contractAddress')
async getUsdtPrice(@Param('contractAddress') contractAddress: string) {
return this.salariesService.getLatestUSDTPrice(contractAddress);
}
@Post('set-salary')
async setSalary(@Body() dto: SetSalaryDto) {
return this.salariesService.setSalary(dto);
}
@Get('salary')
async getSalary(@Body() dto: GetEmployeeSalariesDto) {
return this.salariesService.getSalary(dto);
}
}

View File

@ -0,0 +1,32 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNumber, IsString } from 'class-validator';
export class SalariesDeployDto {
@ApiProperty()
@IsString()
multiSigWallet: string;
}
export class SetSalaryDto {
@ApiProperty()
@IsString()
multiSigWallet: string;
@ApiProperty()
@IsString()
contractAddress: string;
@ApiProperty()
@IsString()
employeeAddress: string;
@ApiProperty()
@IsNumber()
salary: number;
}
export class GetEmployeeSalariesDto {
@ApiProperty()
@IsString()
contractAddress: string;
@ApiProperty()
@IsString()
employeeAddress: string;
}

View File

@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { SalariesService } from './salaries.service';
import { ProviderModule } from 'src/provider/provider.module';
import { SalariesController } from './salaries-interact.controller';
import { MultiSigModule } from '../multi-sig/multi-sig.module';
@Module({
imports: [ProviderModule, MultiSigModule],
controllers: [SalariesController],
providers: [SalariesService],
exports: [SalariesService],
})
export class SalariesModule {}

View File

@ -0,0 +1,75 @@
import { Injectable } from '@nestjs/common';
import { BaseContractService } from '../base-contract.service';
import { ethers } from 'ethers';
import {
GetEmployeeSalariesDto,
SalariesDeployDto,
SetSalaryDto,
} from './salaries.dto';
import * as hre from 'hardhat';
import { MultiSigWalletService } from '../multi-sig/multi-sig.service';
import { ProviderService } from '../../../provider/provider.service';
@Injectable()
export class SalariesService extends BaseContractService {
constructor(
private readonly multiSigWalletService: MultiSigWalletService,
public readonly providerService: ProviderService,
) {
super(providerService);
}
async deploy(dto: SalariesDeployDto): Promise<any> {
const { abi, bytecode } = await hre.artifacts.readArtifact('Salaries');
const signer = await this.providerService.getSigner();
const salaryContract = new ethers.ContractFactory(abi, bytecode, signer);
const myContract = await salaryContract.deploy(
dto.multiSigWallet,
'0xF0d50568e3A7e8259E16663972b11910F89BD8e7',
);
await myContract.waitForDeployment();
return await myContract.getAddress();
}
async getLatestUSDTPrice(contractAddress: string) {
const { abi } = await hre.artifacts.readArtifact('Salaries');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const answer: string = await contract.getLatestUSDTPriceInETH();
return parseInt(answer) / 1e8;
}
async setSalary(dto: SetSalaryDto) {
const { employeeAddress, salary, contractAddress, multiSigWallet } = dto;
const ISubmitMultiSig = new ethers.Interface([
'function setSalary(address employee, uint salaryInUSDT)',
]);
const data = ISubmitMultiSig.encodeFunctionData('setSalary', [
employeeAddress,
salary,
]);
return await this.multiSigWalletService.submitTransaction({
contractAddress: multiSigWallet,
destination: contractAddress,
value: '0',
data,
});
}
async getSalary(dto: GetEmployeeSalariesDto) {
const { employeeAddress, contractAddress } = dto;
const { abi } = await hre.artifacts.readArtifact('Salaries');
const signer = await this.providerService.getSigner();
const contract = new ethers.Contract(contractAddress, abi, signer);
const answer: string = await contract.getSalary(employeeAddress);
return answer;
}
}

View File

@ -1,41 +0,0 @@
import { Injectable } from '@nestjs/common';
import { ethers } from 'ethers';
import { ConfigService } from '@nestjs/config';
import * as hre from 'hardhat';
import { BaseContractService } from './base-contract.service';
@Injectable()
export class SalariesService extends BaseContractService {
getSalaries() {}
async deploy() {
const provider = await this.providerService.getProvider();
const salary = await hre.artifacts.readArtifact('Salaries');
const abi = salary.abi;
const bytecode = salary.deployedBytecode;
const signer = new ethers.Wallet(
this.configService.getOrThrow('POLYGON_PK'),
provider,
);
const salaryContract = new ethers.ContractFactory(
abi,
salary.bytecode,
signer,
);
const myContract = await salaryContract.deploy(
'multisig address',
this.configService.getOrThrow('CHAINLINK_AGGREGATOR_V3'),
);
await myContract.waitForDeployment();
console.log(
'🚀 ~ HardhatService ~ deploySalaryContract ~ myContract:',
myContract,
);
const address = myContract.getAddress();
console.log('🚀 ~ SalariesService ~ deploy ~ address:', address);
}
}

View File

@ -1,7 +1,8 @@
import { NestFactory } from '@nestjs/core';
import { HttpAdapterHost, NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ValidationPipe } from '@nestjs/common';
import { AllExceptionsFilter } from './filters/http.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
@ -13,6 +14,7 @@ async function bootstrap() {
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
app.useGlobalPipes(new ValidationPipe());
app.useGlobalFilters(new AllExceptionsFilter());
await app.listen(3000);
console.log('Swagger avaliable at http://localhost:3000/api');