mirror of
https://github.com/emo2007/block-accounting.git
synced 2024-11-09 20:26:28 +00:00
multisig fully ready + salaries almost ready.
refactor contracts and refactor structure of app. swagger update
This commit is contained in:
parent
ed2f6b9eca
commit
9ec370c8f6
@ -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],
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {}
|
@ -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();
|
||||
});
|
||||
});
|
@ -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);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
export enum ContractType {
|
||||
SALARY,
|
||||
AGREEMENT,
|
||||
}
|
||||
|
||||
export class CreateContractFactoryDto {
|
||||
@ApiProperty({
|
||||
enum: ContractType,
|
||||
})
|
||||
contractType: ContractType;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateContractFactoryDto } from './create-contract-factory.dto';
|
||||
|
||||
export class UpdateContractFactoryDto extends PartialType(CreateContractFactoryDto) {}
|
@ -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();
|
||||
});
|
||||
});
|
@ -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 {}
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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`;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
10
chain-api/src/contract-interact/ethers.helpers.ts
Normal file
10
chain-api/src/contract-interact/ethers.helpers.ts
Normal 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);
|
||||
};
|
@ -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);
|
||||
}
|
||||
}
|
33
chain-api/src/filters/http.filter.ts
Normal file
33
chain-api/src/filters/http.filter.ts
Normal 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
//
|
||||
|
||||
/**
|
||||
|
||||
License
|
||||
sender
|
||||
receiver
|
||||
|
||||
|
||||
*/
|
@ -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) {
|
||||
(
|
||||
,
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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>;
|
||||
}
|
||||
|
60
chain-api/src/hardhat/modules/dto/ethers.dto.ts
Normal file
60
chain-api/src/hardhat/modules/dto/ethers.dto.ts
Normal 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;
|
@ -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 {}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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],
|
||||
})
|
||||
|
@ -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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
32
chain-api/src/hardhat/modules/salaries/salaries.dto.ts
Normal file
32
chain-api/src/hardhat/modules/salaries/salaries.dto.ts
Normal 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;
|
||||
}
|
13
chain-api/src/hardhat/modules/salaries/salaries.module.ts
Normal file
13
chain-api/src/hardhat/modules/salaries/salaries.module.ts
Normal 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 {}
|
75
chain-api/src/hardhat/modules/salaries/salaries.service.ts
Normal file
75
chain-api/src/hardhat/modules/salaries/salaries.service.ts
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user