Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions blockchain/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# .env.example
PRIVATE_KEY=your_64_char_hex_without_0x
INFURA_API_KEY=your_infura_project_id
CONTRACT_ADDRESS=deployed_contract_address_here
32 changes: 32 additions & 0 deletions blockchain/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Node.js / Next.js
node_modules/
.next/
npm-debug.log
package-lock.json
# Python
__pycache__/
*.pyc
.venv/


# Hardhat
artifacts/
cache/
typechain/

# Docker
*.env
docker-compose.override.yml

# VS Code
.vscode/

# OS files
.DS_Store
Thumbs.db

# Project-specific
.env
*.txt
DevSecOps_Blockchain_App.code-workspace

179 changes: 179 additions & 0 deletions blockchain/contracts/ProductRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ProductRegistry {
struct Product {
string name;
string batch;
string manufacturer;
string status;
uint256 timestamp;
bool exists;
}

struct TraceRecord {
string stage;
string company;
string location;
uint256 timestamp;
bool exists;
}

mapping(string => Product) public products;
mapping(string => TraceRecord[]) public productTraces;
mapping(string => uint256) public traceCount;

event ProductRegistered(string productId, string name, string manufacturer);
event ProductStatusUpdated(string productId, string newStatus);
event TraceRecordAdded(string productId, string stage, string company, string location);

modifier productExists(string memory productId) {
require(products[productId].exists, "Product does not exist");
_;
}

function registerProduct(
string memory productId,
string memory name,
string memory batch,
string memory manufacturer
) public {
require(!products[productId].exists, "Product already exists");
require(bytes(productId).length > 0, "Product ID cannot be empty");
require(bytes(name).length > 0, "Product name cannot be empty");
require(bytes(manufacturer).length > 0, "Manufacturer cannot be empty");

products[productId] = Product({
name: name,
batch: batch,
manufacturer: manufacturer,
status: "Created",
timestamp: block.timestamp,
exists: true
});

emit ProductRegistered(productId, name, manufacturer);
}

function updateProductStatus(string memory productId, string memory newStatus)
public
productExists(productId)
{
require(bytes(newStatus).length > 0, "Status cannot be empty");

products[productId].status = newStatus;
emit ProductStatusUpdated(productId, newStatus);
}

function addTraceRecord(
string memory productId,
string memory stage,
string memory company,
string memory location
) public productExists(productId) {
require(bytes(stage).length > 0, "Stage cannot be empty");
require(bytes(company).length > 0, "Company cannot be empty");
require(bytes(location).length > 0, "Location cannot be empty");

TraceRecord memory newTrace = TraceRecord({
stage: stage,
company: company,
location: location,
timestamp: block.timestamp,
exists: true
});

productTraces[productId].push(newTrace);
traceCount[productId] = productTraces[productId].length;

emit TraceRecordAdded(productId, stage, company, location);
}

function getProduct(string memory productId)
public
view
returns (
string memory,
string memory,
string memory,
string memory,
uint256
)
{
require(products[productId].exists, "Product not found");
Product memory p = products[productId];
return (p.name, p.batch, p.manufacturer, p.status, p.timestamp);
}

function getTraceRecord(string memory productId, uint256 index)
public
view
returns (
string memory,
string memory,
string memory,
uint256
)
{
require(products[productId].exists, "Product not found");
require(index < productTraces[productId].length, "Trace record index out of bounds");

TraceRecord memory trace = productTraces[productId][index];
return (trace.stage, trace.company, trace.location, trace.timestamp);
}

function getTraceCount(string memory productId)
public
view
returns (uint256)
{
require(products[productId].exists, "Product not found");
return traceCount[productId];
}

function getAllTraces(string memory productId)
public
view
returns (
string[] memory stages,
string[] memory companies,
string[] memory locations,
uint256[] memory timestamps
)
{
require(products[productId].exists, "Product not found");

uint256 count = productTraces[productId].length;
stages = new string[](count);
companies = new string[](count);
locations = new string[](count);
timestamps = new uint256[](count);

for (uint256 i = 0; i < count; i++) {
TraceRecord memory trace = productTraces[productId][i];
stages[i] = trace.stage;
companies[i] = trace.company;
locations[i] = trace.location;
timestamps[i] = trace.timestamp;
}

return (stages, companies, locations, timestamps);
}

function productExistsCheck(string memory productId)
public
view
returns (bool)
{
return products[productId].exists;
}

// Emergency function to verify contract integrity
function getContractInfo()
public
pure
returns (string memory, string memory)
{
return ("ProductRegistry", "2.0.0");
}
}
24 changes: 24 additions & 0 deletions blockchain/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require("dotenv").config();
console.log("PRIVATE_KEY:", process.env.PRIVATE_KEY);
console.log("INFURA_API_KEY:", process.env.INFURA_API_KEY);
console.log("CONTRACT_ADDRESS:", process.env.CONTRACT_ADDRESS);

require("@nomiclabs/hardhat-ethers");

module.exports = {
solidity: "0.8.20",
defaultNetwork: "sepolia",
networks: {
hardhat: {},
sepolia: {
url: `https://sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY.trim()] : [],
},
},
paths: {
sources: "./contracts",
tests: "./test",
cache: "./cache",
artifacts: "./artifacts",
},
};
16 changes: 16 additions & 0 deletions blockchain/scripts/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const hre = require("hardhat");

async function main() {
console.log("Deploying to Sepolia...");

const ProductRegistry = await hre.ethers.getContractFactory("ProductRegistry");
const registry = await ProductRegistry.deploy();

await registry.deployed();
console.log("✅ Contract deployed to:", registry.address);
}

main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
2 changes: 1 addition & 1 deletion terraform/common/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ provider "aws" {
region = var.aws_region
}

# Tạo VPC..
# Tạo VPC...
module "vpc" {
source = "../modules/vpc"

Expand Down
6 changes: 1 addition & 5 deletions terraform/environments/dev/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ output "dynamodb_table_name" {

output "lambda_functions" {
description = "ARNs of the Lambda functions"
value = {
product_service = module.product_service.function_arn
trace_service = module.trace_service.function_arn
user_service = module.user_service.function_arn
}
value = module.lambda_service.lambda_function_arn
}

output "api_gateway_endpoint" {
Expand Down
2 changes: 1 addition & 1 deletion terraform/environments/dev/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ variable "public_subnets" {
variable "app_version" {
description = "Version of the application"
type = string
default = "158b2cd63572d3115e89204ad3786762eac77996"
default = "158b2cd63572d3115e89204ad3786762eac77996"
}

variable "cognito_user_pool_id" {
Expand Down
2 changes: 2 additions & 0 deletions terraform/environments/prod/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ terraform {
}
}

#run

provider "aws" {
region = var.aws_region
}
Expand Down
6 changes: 1 addition & 5 deletions terraform/environments/prod/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ output "dynamodb_table_name" {

output "lambda_functions" {
description = "ARNs of the Lambda functions"
value = {
product_service = module.product_service.function_arn
trace_service = module.trace_service.function_arn
user_service = module.user_service.function_arn
}
value = module.lambda_service.lambda_function_arn
}

output "api_gateway_endpoint" {
Expand Down
2 changes: 1 addition & 1 deletion terraform/environments/prod/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ variable "public_subnets" {
variable "app_version" {
description = "Version of the application"
type = string
default = "158b2cd63572d3115e89204ad3786762eac77996"
default = "158b2cd63572d3115e89204ad3786762eac77996"
}

variable "cognito_user_pool_id" {
Expand Down
Loading