Skip to content

Instantly share code, notes, and snippets.

@asaidimu
Last active June 23, 2024 15:09
Show Gist options
  • Select an option

  • Save asaidimu/827194698cf2d1f7adfe1e2995a3cd02 to your computer and use it in GitHub Desktop.

Select an option

Save asaidimu/827194698cf2d1f7adfe1e2995a3cd02 to your computer and use it in GitHub Desktop.
Tracking a project with blockchain.
import { v4 as uuidv4 } from 'uuid';
// UUID generation function
const generateUUID = (): string => {
return uuidv4();
};
// User interface
interface User {
userId: string;
name: string;
department: string;
email: string;
}
// Internal Department interface
interface InternalDepartment {
departmentId: string;
name: string;
manager: string; // UUID of User
}
// Contractor interface
interface Contractor {
contractorId: string;
name: string;
contactPerson: string; // UUID of User
company: string;
}
// Financial Officer interface
interface FinancialOfficer {
officerId: string;
name: string;
department: string;
email: string;
}
// Task interface
interface Task {
taskId: string;
createdBy: string; // UUID of User
createdTimestamp: string; // ISO string
description: string;
function: string;
policy: string;
proposer: string; // UUID of User
thesis: string;
currentStage: TaskStage;
stages: TaskStage[];
approvals: Approval[];
budget?: Budget; // Optional budget information
handler?: string; // UUID of InternalDepartment or Contractor
reason?: string; // Reason for hiring contractor or internal handling
financialApprovals?: FinancialApproval[]; // Array of FinancialApprovals
totalEstimatedCost?: number; // Total estimated cost for the task
performanceReview?: PerformanceReview; // Performance review by committee
financialReceipts?: FinancialReceipt[]; // Array of FinancialReceipts
completionStatus: 'Pending' | 'Completed'; // Task completion status
}
// TaskStage interface
interface TaskStage {
stageId: string;
taskId: string; // UUID of Task
stageName: string;
startDate: string; // ISO string
endDate?: string; // ISO string
comments?: string;
}
// Approval interface
interface Approval {
approvalId: string;
approver: string; // UUID of User or FinancialOfficer
timestamp: string; // ISO string
status: 'Pending' | 'Approved' | 'Rejected';
comments?: string;
}
// Budget interface
interface Budget {
taskId: string; // UUID of Task
subcommittee: string; // UUID of committee or subcommittee
resources: BudgetResource[];
}
// BudgetResource interface
interface BudgetResource {
resourceId: string; // UUID of Resource
reason: string; // Reason for resource allocation
cost: number; // Cost of resource
}
// FinancialApproval interface
interface FinancialApproval {
approvalId: string;
taskId: string; // UUID of Task
approver: string; // UUID of FinancialOfficer
timestamp: string; // ISO string
status: 'Pending' | 'Approved' | 'Rejected';
comments?: string;
}
// PerformanceReview interface
interface PerformanceReview {
taskId: string; // UUID of Task
committee: string; // UUID of committee or subcommittee
comments: string; // Review comments
}
// FinancialReceipt interface
interface FinancialReceipt {
receiptId: string;
taskId: string; // UUID of Task
resourceId: string; // UUID of Resource
approvedBy: string; // UUID of FinancialOfficer
approvalTimestamp: string; // ISO string
receiptDetails: string;
}
// Block interface for blockchain
interface Block {
index: number;
previousHash: string;
timestamp: number;
data: Task;
hash: string;
}
// Blockchain class
class Blockchain {
chain: Block[];
constructor() {
this.chain = [];
// Genesis block creation (initial block in the blockchain)
this.createGenesisBlock();
}
// Create genesis block
private createGenesisBlock() {
const genesisBlock: Block = {
index: 0,
previousHash: '0',
timestamp: Date.now(),
data: null, // No data for genesis block
hash: ''
};
genesisBlock.hash = this.calculateHash(genesisBlock);
this.chain.push(genesisBlock);
}
// Calculate hash for a block
private calculateHash(block: Block): string {
const { index, previousHash, timestamp, data } = block;
const blockString = `${index}${previousHash}${timestamp}${JSON.stringify(data)}`;
return uuidv4(); // Placeholder for actual hash calculation, using UUID for simplicity
}
// Get latest block in the chain
private getLatestBlock(): Block {
return this.chain[this.chain.length - 1];
}
// Add a new block to the chain
addBlock(data: Task): void {
const previousBlock = this.getLatestBlock();
const newIndex = previousBlock.index + 1;
const newBlock: Block = {
index: newIndex,
previousHash: previousBlock.hash,
timestamp: Date.now(),
data,
hash: ''
};
newBlock.hash = this.calculateHash(newBlock);
this.chain.push(newBlock);
}
// Validate blockchain integrity (simple check)
isChainValid(): boolean {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
// Check if hashes are correct
if (currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
return true;
}
}
// Example Usage
const blockchain = new Blockchain();
// Example data creation
const user1: User = {
userId: generateUUID(),
name: 'Alice',
department: 'IT',
email: '[email protected]'
};
const committee: string = generateUUID(); // UUID for committee
const taskProposal: Task = {
taskId: generateUUID(),
createdBy: user1.userId,
createdTimestamp: new Date().toISOString(),
description: 'Build a school in Maralal',
function: 'Education',
policy: 'Education Policy 2024',
proposer: user1.userId,
thesis: 'A school in Maralal will provide access to education for children in the region.',
currentStage: {
stageId: generateUUID(),
taskId: '', // To be filled later during insertion
stageName: 'Proposal',
startDate: new Date().toISOString()
},
stages: [],
approvals: [],
completionStatus: 'Pending'
};
// Add initial proposal to blockchain
blockchain.addBlock(taskProposal);
// Committee reviews the proposal and moves to deliberation stage
const taskWithDeliberation: Task = {
...taskProposal,
currentStage: {
stageId: generateUUID(),
taskId: taskProposal.taskId,
stageName: 'Deliberation',
startDate: new Date().toISOString()
}
};
blockchain.addBlock(taskWithDeliberation);
// Committee approves the proposal
const approvedTask: Task = {
...taskWithDeliberation,
currentStage: {
...taskWithDeliberation.currentStage,
endDate: new Date().toISOString()
},
approvals: [
{
approvalId: generateUUID(),
approver: committee,
timestamp: new Date().toISOString(),
status: 'Approved',
comments: 'Approved for building the school in Maralal.'
}
]
};
blockchain.addBlock(approvedTask);
// Subcommittee develops budget and decides on handling
const budget: Budget = {
taskId: approvedTask.taskId,
subcommittee: committee,
resources: [
{
resourceId: generateUUID(),
reason: 'Construction materials',
cost: 50000
},
{
resourceId: generateUUID(),
reason: 'Labor costs',
cost: 80000
}
]
};
const taskWithBudget: Task = {
...approvedTask,
budget,
handler: generateUUID(), // Assuming hiring contractor
reason: 'Contractor selected for construction'
};
blockchain.addBlock(taskWithBudget);
// Financial officer approves funds
const financialApproval: FinancialApproval = {
approvalId: generateUUID(),
taskId: taskWithBudget.taskId,
approver: generateUUID(), // UUID of financial officer
timestamp: new Date().toISOString(),
status: 'Approved',
comments: 'Approved funds allocation for school construction in Maralal.'
};
const taskWithFinancialApproval: Task = {
...taskWithBudget,
financialApprovals: [financialApproval],
totalEstimatedCost: budget.resources.reduce((total, resource) => total + resource.cost, 0)
};
blockchain.addBlock(taskWithFinancialApproval);
// Performance review and financial receipts
const performanceReview: PerformanceReview = {
taskId: taskWithFinancialApproval.taskId,
committee,
comments: 'Construction completed on time and within budget.'
};
const financialReceipts: FinancialReceipt[] = [
{
receiptId: generateUUID(),
taskId: taskWithFinancialApproval.taskId,
resourceId: budget.resources[0].resourceId, // Assuming first resource for example
approvedBy: financialApproval.approver,
approvalTimestamp: new Date().toISOString(),
receiptDetails: 'Receipt for construction materials'
},
{
receiptId: generateUUID(),
taskId: taskWithFinancialApproval.taskId,
resourceId: budget.resources[1].resourceId, // Assuming second resource for
approvedBy: financialApproval.approver,
approvalTimestamp: new Date().toISOString(),
receiptDetails: 'Receipt for labor costs'
}
];
const taskCompleted: Task = {
...taskWithFinancialApproval,
performanceReview,
financialReceipts,
completionStatus: 'Completed'
};
blockchain.addBlock(taskCompleted);
// Example of validating the blockchain
console.log('Is blockchain valid?', blockchain.isChainValid());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment