agreement update, contract tested and fixed, readme init
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.idea
|
.idea
|
||||||
.env
|
.env
|
||||||
|
.vscode
|
8
.idea/.gitignore
vendored
@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/block-accounting.iml" filepath="$PROJECT_DIR$/.idea/block-accounting.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="PrettierConfiguration">
|
|
||||||
<option name="myConfigurationMode" value="AUTOMATIC" />
|
|
||||||
<option name="myRunOnSave" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"solidity.compileUsingRemoteVersion": "v0.8.25+commit.b61c2a91"
|
|
||||||
}
|
|
21
README.md
@ -1,11 +1,14 @@
|
|||||||
![LOGIN FLOW](./login-flow.png "Login")
|
### CHAIN-API
|
||||||
|
|
||||||
[//]: # (![Example architecture](./arch.png "Arch"))
|
- ### Multi-Sig Deploy
|
||||||
![License](./license.png "Arch")
|
![Alt Text](./excalidraw/multisig.png)
|
||||||
![Salaries](./salaries.png "Arch")
|
|
||||||
|
|
||||||
# Registration Flow
|
- ### Payroll Deploy
|
||||||
|
![Alt Text](./excalidraw/payroll-deploy.png)
|
||||||
- On First Login - Owner inputs his SEED_KEY (mnemonic), creates an organization, we save its seed hash for future login and signing internal txs.
|
- ### Payroll
|
||||||
- When inviting an employee to organization- we generate an invitation link, then after clicking on this link - the user is asked for seed, if he's already registered or able to generate a seed for new account.
|
![set-salary.png](excalidraw%2Fset-salary.png)
|
||||||
-
|
![payroll.png](excalidraw%2Fpayroll.png)
|
||||||
|
- ### License
|
||||||
|
![license-deploy.png](excalidraw%2Flicense-deploy.png)
|
||||||
|
![data-request-license.png](excalidraw%2Fdata-request-license.png)
|
||||||
|
![license-payout-2of3steps.png](excalidraw%2Flicense-payout-2of3steps.png)![3step-license-payout.png](excalidraw%2F3step-license-payout.png)
|
@ -4,6 +4,8 @@ import { AppService } from './app.service';
|
|||||||
|
|
||||||
import { ContractInteractModule } from './contract-interact/contract-interact.module';
|
import { ContractInteractModule } from './contract-interact/contract-interact.module';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { EthereumModule } from './ethereum/ethereum.module';
|
||||||
|
import { AgreementModule } from './contract-interact/agreement/agreement.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -11,6 +13,8 @@ import { ConfigModule } from '@nestjs/config';
|
|||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
}),
|
}),
|
||||||
ContractInteractModule,
|
ContractInteractModule,
|
||||||
|
EthereumModule,
|
||||||
|
AgreementModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
@ -4,7 +4,7 @@ import { ProviderModule } from './provider/provider.module';
|
|||||||
@Module({
|
@Module({
|
||||||
imports: [ProviderModule],
|
imports: [ProviderModule],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [ProviderModule],
|
providers: [],
|
||||||
exports: [ProviderModule],
|
exports: [ProviderModule],
|
||||||
})
|
})
|
||||||
export class BaseModule {}
|
export class BaseModule {}
|
||||||
|
@ -18,11 +18,7 @@ export class ProviderService {
|
|||||||
if (this.provider) {
|
if (this.provider) {
|
||||||
return this.provider;
|
return this.provider;
|
||||||
}
|
}
|
||||||
const polygonProvider = new ethers.JsonRpcProvider(
|
this.provider = new ethers.JsonRpcProvider(this.nodeUrl, this.networkId);
|
||||||
this.nodeUrl,
|
|
||||||
this.networkId,
|
|
||||||
);
|
|
||||||
this.provider = polygonProvider;
|
|
||||||
return this.provider;
|
return this.provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ export const CHAINLINK = {
|
|||||||
},
|
},
|
||||||
JOB_IDS: {
|
JOB_IDS: {
|
||||||
UINT: 'a8356f48569c434eaa4ac5fcb4db5cc0',
|
UINT: 'a8356f48569c434eaa4ac5fcb4db5cc0',
|
||||||
|
BOOL: '43309009a154495cb2ed794233e6ff56',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import { Body, Controller, Post, Get, Param } from '@nestjs/common';
|
||||||
|
import { AgreementService } from './agreement.service';
|
||||||
|
import {
|
||||||
|
DeployAgreementDto,
|
||||||
|
GetAgreementInfoDto,
|
||||||
|
RequestAgreementDto,
|
||||||
|
} from './agreement.dto';
|
||||||
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
@ApiTags('Agreement')
|
||||||
|
@Controller('agreements')
|
||||||
|
export class AgreementController {
|
||||||
|
constructor(private readonly agreementService: AgreementService) {}
|
||||||
|
|
||||||
|
@Post('deploy')
|
||||||
|
async deployAgreement(@Body() deployDto: DeployAgreementDto) {
|
||||||
|
return await this.agreementService.deploy(deployDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':contractAddress')
|
||||||
|
async getAgreementResponse(
|
||||||
|
@Param('contractAddress') contractAddress: string,
|
||||||
|
) {
|
||||||
|
return await this.agreementService.getResponse({ contractAddress });
|
||||||
|
}
|
||||||
|
@Post('request')
|
||||||
|
async requestAgreement(@Body() requestDto: RequestAgreementDto) {
|
||||||
|
return await this.agreementService.request(requestDto);
|
||||||
|
}
|
||||||
|
}
|
21
chain-api/src/contract-interact/agreement/agreement.dto.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsString, IsUrl } from 'class-validator';
|
||||||
|
|
||||||
|
export class DeployAgreementDto {
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
multiSigWallet: string;
|
||||||
|
}
|
||||||
|
export class GetAgreementInfoDto {
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
contractAddress: string;
|
||||||
|
}
|
||||||
|
export class RequestAgreementDto extends GetAgreementInfoDto {
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
multiSigWallet: string;
|
||||||
|
@ApiProperty()
|
||||||
|
@IsUrl()
|
||||||
|
url: string;
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { AgreementController } from './agreement.controller';
|
||||||
|
import { AgreementService } from './agreement.service';
|
||||||
|
import { BaseModule } from '../../base/base.module';
|
||||||
|
import { MultiSigModule } from '../multi-sig/multi-sig.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [BaseModule, MultiSigModule],
|
||||||
|
controllers: [AgreementController],
|
||||||
|
providers: [AgreementService],
|
||||||
|
|
||||||
|
exports: [],
|
||||||
|
})
|
||||||
|
export class AgreementModule {}
|
@ -0,0 +1,75 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { BaseContractService } from '../../base/base-contract.service';
|
||||||
|
import * as hre from 'hardhat';
|
||||||
|
import { ethers } from 'ethers';
|
||||||
|
import { CHAINLINK } from '../../config/chainlink.config';
|
||||||
|
import {
|
||||||
|
DeployAgreementDto,
|
||||||
|
GetAgreementInfoDto,
|
||||||
|
RequestAgreementDto,
|
||||||
|
} from './agreement.dto';
|
||||||
|
import { MultiSigWalletService } from '../multi-sig/multi-sig.service';
|
||||||
|
import { ProviderService } from '../../base/provider/provider.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AgreementService extends BaseContractService {
|
||||||
|
constructor(
|
||||||
|
public readonly providerService: ProviderService,
|
||||||
|
public readonly multiSigService: MultiSigWalletService,
|
||||||
|
) {
|
||||||
|
super(providerService);
|
||||||
|
}
|
||||||
|
async deploy(dto: DeployAgreementDto): Promise<any> {
|
||||||
|
const { multiSigWallet } = dto;
|
||||||
|
const { bytecode } = await hre.artifacts.readArtifact('Agreement');
|
||||||
|
|
||||||
|
const abiCoder = ethers.AbiCoder.defaultAbiCoder();
|
||||||
|
|
||||||
|
const abiEncodedConstructorArguments = abiCoder.encode(
|
||||||
|
['address', 'address', 'string', 'uint', 'address'],
|
||||||
|
[
|
||||||
|
CHAINLINK.AMOY.CHAINLINK_TOKEN,
|
||||||
|
CHAINLINK.AMOY.ORACLE_ADDRESS,
|
||||||
|
CHAINLINK.AMOY.JOB_IDS.BOOL,
|
||||||
|
0,
|
||||||
|
multiSigWallet,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
const fullBytecode = bytecode + abiEncodedConstructorArguments.substring(2);
|
||||||
|
const submitData = await this.multiSigService.submitTransaction({
|
||||||
|
contractAddress: multiSigWallet,
|
||||||
|
destination: null,
|
||||||
|
value: '0',
|
||||||
|
data: fullBytecode,
|
||||||
|
});
|
||||||
|
delete submitData.data;
|
||||||
|
return submitData;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getResponse(dto: GetAgreementInfoDto) {
|
||||||
|
const { contractAddress } = dto;
|
||||||
|
const { abi } = await hre.artifacts.readArtifact('Agreement');
|
||||||
|
const signer = await this.providerService.getSigner();
|
||||||
|
|
||||||
|
const contract = new ethers.Contract(contractAddress, abi, signer);
|
||||||
|
|
||||||
|
const answer = await contract.response();
|
||||||
|
return answer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
async request(dto: RequestAgreementDto) {
|
||||||
|
const { multiSigWallet, contractAddress, url } = dto;
|
||||||
|
|
||||||
|
const ISubmitMultiSig = new ethers.Interface([
|
||||||
|
'function request(string memory url)',
|
||||||
|
]);
|
||||||
|
const data = ISubmitMultiSig.encodeFunctionData('request', [url]);
|
||||||
|
|
||||||
|
return await this.multiSigService.submitTransaction({
|
||||||
|
contractAddress: multiSigWallet,
|
||||||
|
destination: contractAddress,
|
||||||
|
value: '0',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { IsArray, IsNumber, IsString } from 'class-validator';
|
import { IsArray, IsNumber, IsString, IsUrl } from 'class-validator';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
export class GetLicenseInfoDto {
|
export class GetLicenseInfoDto {
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
@ -24,6 +24,9 @@ export class RequestLicenseDto extends GetLicenseInfoDto {
|
|||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
@IsString()
|
@IsString()
|
||||||
multiSigWallet: string;
|
multiSigWallet: string;
|
||||||
|
@ApiProperty()
|
||||||
|
@IsUrl()
|
||||||
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetLicenseResponseDto extends GetLicenseInfoDto {}
|
export class GetLicenseResponseDto extends GetLicenseInfoDto {}
|
||||||
|
@ -10,23 +10,25 @@ import {
|
|||||||
RequestLicenseDto,
|
RequestLicenseDto,
|
||||||
SetPayoutContractDto,
|
SetPayoutContractDto,
|
||||||
} from './license.dto';
|
} from './license.dto';
|
||||||
import { MultiSigWalletService } from '../multi-sig/multi-sig.service';
|
|
||||||
import { ProviderService } from '../../base/provider/provider.service';
|
|
||||||
import { CHAINLINK } from '../../config/chainlink.config';
|
import { CHAINLINK } from '../../config/chainlink.config';
|
||||||
|
import { ProviderService } from '../../base/provider/provider.service';
|
||||||
|
import { MultiSigWalletService } from '../multi-sig/multi-sig.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LicenseService extends BaseContractService {
|
export class LicenseService extends BaseContractService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly multiSigService: MultiSigWalletService,
|
|
||||||
public readonly providerService: ProviderService,
|
public readonly providerService: ProviderService,
|
||||||
|
public readonly multiSigService: MultiSigWalletService,
|
||||||
) {
|
) {
|
||||||
super(providerService);
|
super(providerService);
|
||||||
}
|
}
|
||||||
async request(dto: RequestLicenseDto) {
|
async request(dto: RequestLicenseDto) {
|
||||||
const { multiSigWallet, contractAddress } = dto;
|
const { multiSigWallet, contractAddress, url } = dto;
|
||||||
|
|
||||||
const ISubmitMultiSig = new ethers.Interface(['function request()']);
|
const ISubmitMultiSig = new ethers.Interface([
|
||||||
const data = ISubmitMultiSig.encodeFunctionData('request');
|
'function request(string memory url)',
|
||||||
|
]);
|
||||||
|
const data = ISubmitMultiSig.encodeFunctionData('request', [url]);
|
||||||
|
|
||||||
return await this.multiSigService.submitTransaction({
|
return await this.multiSigService.submitTransaction({
|
||||||
contractAddress: multiSigWallet,
|
contractAddress: multiSigWallet,
|
||||||
@ -46,7 +48,6 @@ export class LicenseService extends BaseContractService {
|
|||||||
const contract = new ethers.Contract(contractAddress, abi, signer);
|
const contract = new ethers.Contract(contractAddress, abi, signer);
|
||||||
|
|
||||||
const answer: bigint = await contract.totalPayoutInUSD();
|
const answer: bigint = await contract.totalPayoutInUSD();
|
||||||
console.log('=>(license.service.ts:45) answer', answer);
|
|
||||||
return answer.toString();
|
return answer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,17 +7,17 @@ import {
|
|||||||
SetSalaryDto,
|
SetSalaryDto,
|
||||||
} from './salaries.dto';
|
} from './salaries.dto';
|
||||||
import * as hre from 'hardhat';
|
import * as hre from 'hardhat';
|
||||||
import { MultiSigWalletService } from '../multi-sig/multi-sig.service';
|
|
||||||
import { BaseContractService } from '../../base/base-contract.service';
|
import { BaseContractService } from '../../base/base-contract.service';
|
||||||
import { ProviderService } from '../../base/provider/provider.service';
|
|
||||||
import { DepositContractDto } from '../multi-sig.dto';
|
import { DepositContractDto } from '../multi-sig.dto';
|
||||||
import { CHAINLINK } from '../../config/chainlink.config';
|
import { CHAINLINK } from '../../config/chainlink.config';
|
||||||
|
import { ProviderService } from '../../base/provider/provider.service';
|
||||||
|
import { MultiSigWalletService } from '../multi-sig/multi-sig.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SalariesService extends BaseContractService {
|
export class SalariesService extends BaseContractService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly multiSigWalletService: MultiSigWalletService,
|
|
||||||
public readonly providerService: ProviderService,
|
public readonly providerService: ProviderService,
|
||||||
|
public readonly multiSigService: MultiSigWalletService,
|
||||||
) {
|
) {
|
||||||
super(providerService);
|
super(providerService);
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ export class SalariesService extends BaseContractService {
|
|||||||
salary,
|
salary,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return await this.multiSigWalletService.submitTransaction({
|
return await this.multiSigService.submitTransaction({
|
||||||
contractAddress: multiSigWallet,
|
contractAddress: multiSigWallet,
|
||||||
destination: contractAddress,
|
destination: contractAddress,
|
||||||
value: '0',
|
value: '0',
|
||||||
@ -87,7 +87,7 @@ export class SalariesService extends BaseContractService {
|
|||||||
employeeAddress,
|
employeeAddress,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return await this.multiSigWalletService.submitTransaction({
|
return await this.multiSigService.submitTransaction({
|
||||||
contractAddress: multiSigWallet,
|
contractAddress: multiSigWallet,
|
||||||
destination: contractAddress,
|
destination: contractAddress,
|
||||||
value: '0',
|
value: '0',
|
||||||
|
12
chain-api/src/ethereum/ethereum.controller.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Controller, Get, Param } from '@nestjs/common';
|
||||||
|
import { EthereumService } from './ethereum.service';
|
||||||
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
@ApiTags('Ethereum')
|
||||||
|
@Controller()
|
||||||
|
export class EthereumController {
|
||||||
|
constructor(private readonly ethereumService: EthereumService) {}
|
||||||
|
@Get('/address/:privateKey')
|
||||||
|
async getAddressFromPrivateKey(@Param('privateKey') privateKey: string) {
|
||||||
|
return this.ethereumService.getAddressFromPrivateKey(privateKey);
|
||||||
|
}
|
||||||
|
}
|
11
chain-api/src/ethereum/ethereum.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { EthereumController } from './ethereum.controller';
|
||||||
|
import { EthereumService } from './ethereum.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [],
|
||||||
|
controllers: [EthereumController],
|
||||||
|
providers: [EthereumService],
|
||||||
|
exports: [],
|
||||||
|
})
|
||||||
|
export class EthereumModule {}
|
10
chain-api/src/ethereum/ethereum.service.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ethers } from 'ethers';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EthereumService {
|
||||||
|
async getAddressFromPrivateKey(privateKey: string) {
|
||||||
|
const wallet = new ethers.Wallet(privateKey);
|
||||||
|
return wallet.address;
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ export class AllExceptionsFilter implements ExceptionFilter {
|
|||||||
|
|
||||||
const responseBody = {
|
const responseBody = {
|
||||||
statusCode: httpStatus,
|
statusCode: httpStatus,
|
||||||
error: exception?.info?.error.message || exception.toString(),
|
error: exception?.info?.error?.message || exception.toString(),
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,30 +4,20 @@ pragma solidity ^0.8.17;
|
|||||||
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
|
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
|
||||||
import "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
|
import "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
|
||||||
|
|
||||||
/**
|
contract Agreement is ChainlinkClient, ConfirmedOwner {
|
||||||
* Request testnet LINK and ETH here: https://faucets.chain.link/
|
|
||||||
* Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
contract LinkWellBoolConsumerContractExample is ChainlinkClient, ConfirmedOwner {
|
|
||||||
using Chainlink for Chainlink.Request;
|
using Chainlink for Chainlink.Request;
|
||||||
|
|
||||||
address private oracleAddress;
|
address private oracleAddress;
|
||||||
bytes32 private jobId;
|
bytes32 private jobId;
|
||||||
uint256 private fee;
|
uint256 private fee;
|
||||||
|
address public multisigWallet;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address _chainLinkToken,
|
address _chainLinkToken,
|
||||||
address _oracleAddress,
|
address _oracleAddress,
|
||||||
string memory _jobId,
|
string memory _jobId,
|
||||||
uint _fee,
|
uint _fee,
|
||||||
address _multiSigAddress,
|
address _multiSigAddress
|
||||||
address[] memory _owners,
|
|
||||||
uint[] memory _shares
|
|
||||||
) ConfirmedOwner(_multiSigAddress) {
|
) ConfirmedOwner(_multiSigAddress) {
|
||||||
|
|
||||||
_setChainlinkToken(_chainLinkToken);
|
_setChainlinkToken(_chainLinkToken);
|
||||||
@ -41,32 +31,18 @@ contract LinkWellBoolConsumerContractExample is ChainlinkClient, ConfirmedOwner
|
|||||||
multisigWallet = _multiSigAddress;
|
multisigWallet = _multiSigAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() ConfirmedOwner(msg.sender) {
|
|
||||||
_setChainlinkToken(0x0Fd9e8d3aF1aaee056EB9e802c3A762a667b1904);
|
|
||||||
setOracleAddress(0xd36c6B1777c7f3Db1B3201bDD87081A9045B7b46);
|
|
||||||
setJobId("43309009a154495cb2ed794233e6ff56");
|
|
||||||
setFeeInHundredthsOfLink(0); // 0 LINK
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a request to the Chainlink oracle
|
// Send a request to the Chainlink oracle
|
||||||
function request() public {
|
function request(string memory url) public {
|
||||||
|
|
||||||
Chainlink.Request memory req = _buildOperatorRequest(jobId, this.fulfill.selector);
|
Chainlink.Request memory req = _buildOperatorRequest(jobId, this.fulfill.selector);
|
||||||
|
|
||||||
// DEFINE THE REQUEST PARAMETERS (example)
|
req._add('method', 'GET');
|
||||||
req._add('method', 'POST');
|
req._add('url', url);
|
||||||
req._add('url', 'https://httpbin.org/post');
|
req._add('headers', '["content-type", "application/json"]');
|
||||||
req._add('headers', '["accept", "application/json", "set-cookie", "sid=14A52"]');
|
req._add('body', '');
|
||||||
req._add('body', '{"data":[{"coin":"BTC","isActive":false},{"coin":"ETH","isActive":false},{"coin":"LINK","isActive":true}]}');
|
req._add('contact', '');
|
||||||
req._add('contact', ''); // PLEASE ENTER YOUR CONTACT INFO. this allows us to notify you in the event of any emergencies related to your request (ie, bugs, downtime, etc.). example values: 'derek_linkwellnodes.io' (Discord handle) OR 'derek@linkwellnodes.io' OR '+1-617-545-4721'
|
req._add('path', '');
|
||||||
|
|
||||||
// The following curl command simulates the above request parameters:
|
|
||||||
// curl 'https://httpbin.org/post' --request 'POST' --header 'content-type: application/json' --header 'set-cookie: sid=14A52' --data '{"data":[{"coin":"BTC","isActive":false},{"coin":"ETH","isActive":false},{"coin":"LINK","isActive":true}]}'
|
|
||||||
|
|
||||||
// PROCESS THE RESULT (example)
|
|
||||||
req._add('path', 'json,data,2,isActive');
|
|
||||||
|
|
||||||
// Send the request to the Chainlink oracle
|
|
||||||
_sendOperatorRequest(req, fee);
|
_sendOperatorRequest(req, fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,9 +51,8 @@ contract LinkWellBoolConsumerContractExample is ChainlinkClient, ConfirmedOwner
|
|||||||
// Receive the result from the Chainlink oracle
|
// Receive the result from the Chainlink oracle
|
||||||
event RequestFulfilled(bytes32 indexed requestId);
|
event RequestFulfilled(bytes32 indexed requestId);
|
||||||
function fulfill(bytes32 requestId, bool data) public recordChainlinkFulfillment(requestId) {
|
function fulfill(bytes32 requestId, bool data) public recordChainlinkFulfillment(requestId) {
|
||||||
// Process the oracle response
|
emit RequestFulfilled(requestId);
|
||||||
// emit RequestFulfilled(requestId); // (optional) emits this event in the on-chain transaction logs, allowing Web3 applications to listen for this transaction
|
response = data;
|
||||||
response = data; // example value: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update oracle address
|
// Update oracle address
|
||||||
|
@ -55,10 +55,6 @@ contract StreamingRightsManagement is ChainlinkClient, ConfirmedOwner {
|
|||||||
owners.push(_owners[i]);
|
owners.push(_owners[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//get share
|
|
||||||
//update share
|
|
||||||
//change payout address
|
|
||||||
//
|
|
||||||
modifier hasValidPayoutContract() {
|
modifier hasValidPayoutContract() {
|
||||||
require(address(payoutContract) != address(0), "payoutContract not initialized");
|
require(address(payoutContract) != address(0), "payoutContract not initialized");
|
||||||
_;
|
_;
|
||||||
@ -73,26 +69,20 @@ contract StreamingRightsManagement is ChainlinkClient, ConfirmedOwner {
|
|||||||
payoutContract = Payroll(_payoutAddress);
|
payoutContract = Payroll(_payoutAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Send a request to the Chainlink oracle
|
// Send a request to the Chainlink oracle
|
||||||
function request() external onlyOwner{
|
function request(string memory url) external onlyOwner{
|
||||||
|
|
||||||
Chainlink.Request memory req = _buildOperatorRequest(jobId, this.fulfill.selector);
|
Chainlink.Request memory req = _buildOperatorRequest(jobId, this.fulfill.selector);
|
||||||
|
|
||||||
// DEFINE THE REQUEST PARAMETERS (example)
|
|
||||||
req._add('method', 'GET');
|
req._add('method', 'GET');
|
||||||
req._add('url', 'https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH&tsyms=USD,EUR');
|
req._add('url', url);
|
||||||
req._add('headers', '["content-type", "application/json", "set-cookie", "sid=14A52"]');
|
|
||||||
req._add('body', '');
|
|
||||||
req._add('contact', ''); // PLEASE ENTER YOUR CONTACT INFO. this allows us to notify you in the event of any emergencies related to your request (ie, bugs, downtime, etc.). example values: 'derek_linkwellnodes.io' (Discord handle) OR 'derek@linkwellnodes.io' OR '+1-617-545-4721'
|
|
||||||
|
|
||||||
// The following curl command simulates the above request parameters:
|
//if returns just int - then empty path
|
||||||
// curl 'https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,ETH&tsyms=USD,EUR' --request 'GET' --header 'content-type: application/json' --header 'set-cookie: sid=14A52'
|
req._add('path', '');
|
||||||
|
|
||||||
// PROCESS THE RESULT (example)
|
|
||||||
req._add('path', 'ETH,USD');
|
|
||||||
req._addInt('multiplier', 10 ** 18);
|
req._addInt('multiplier', 10 ** 18);
|
||||||
// Send the request to the Chainlink oracle
|
req._add('headers', '["content-type", "application/json"]');
|
||||||
|
req._add('body', '');
|
||||||
|
req._add('contact', '');
|
||||||
_sendOperatorRequest(req, fee);
|
_sendOperatorRequest(req, fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,9 +92,7 @@ contract StreamingRightsManagement is ChainlinkClient, ConfirmedOwner {
|
|||||||
event RequestFulfilled(bytes32 indexed requestId);
|
event RequestFulfilled(bytes32 indexed requestId);
|
||||||
|
|
||||||
function fulfill(bytes32 requestId, uint256 data) public recordChainlinkFulfillment(requestId) {
|
function fulfill(bytes32 requestId, uint256 data) public recordChainlinkFulfillment(requestId) {
|
||||||
// Process the oracle response
|
totalPayoutInUSD = data / 1e18;
|
||||||
// emit RequestFulfilled(requestId); // (optional) emits this event in the on-chain transaction logs, allowing Web3 applications to listen for this transaction
|
|
||||||
totalPayoutInUSD = data / 1e18 / 100; // example value: 1875870000000000000000 (1875.87 before "multiplier" is applied)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function payout() external onlyOwner hasValidPayoutContract{
|
function payout() external onlyOwner hasValidPayoutContract{
|
||||||
|
4
docs.md
@ -1,4 +0,0 @@
|
|||||||
# links
|
|
||||||
|
|
||||||
chainlink-feeds amoy
|
|
||||||
https://docs.chain.link/data-feeds/price-feeds/addresses?network=polygon&page=1
|
|
1603
excalidraw/3step-license-payout.excalidraw
Normal file
BIN
excalidraw/3step-license-payout.png
Normal file
After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 238 KiB |
1772
excalidraw/data-request-license.excalidraw
Normal file
BIN
excalidraw/data-request-license.png
Normal file
After Width: | Height: | Size: 130 KiB |
1038
excalidraw/license-deploy.excalidraw
Normal file
BIN
excalidraw/license-deploy.png
Normal file
After Width: | Height: | Size: 113 KiB |
2088
excalidraw/license-payout-2of3steps.excalidraw
Normal file
BIN
excalidraw/license-payout-2of3steps.png
Normal file
After Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 182 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
1004
excalidraw/multisig.excalidraw
Normal file
BIN
excalidraw/multisig.png
Normal file
After Width: | Height: | Size: 108 KiB |
1014
excalidraw/payroll-deploy.excalidraw
Normal file
BIN
excalidraw/payroll-deploy.png
Normal file
After Width: | Height: | Size: 42 KiB |
1250
excalidraw/payroll.excalidraw
Normal file
BIN
excalidraw/payroll.png
Normal file
After Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 282 KiB |
1033
excalidraw/set-salary.excalidraw
Normal file
BIN
excalidraw/set-salary.png
Normal file
After Width: | Height: | Size: 88 KiB |