Skip to content

Commit 41f0d94

Browse files
authored
Merge pull request #7 from Giabaoday/main
Sync
2 parents 5db82b5 + 732f729 commit 41f0d94

11 files changed

Lines changed: 262 additions & 13 deletions

File tree

blockchain/.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# .env.example
2+
PRIVATE_KEY=your_64_char_hex_without_0x
3+
INFURA_API_KEY=your_infura_project_id
4+
CONTRACT_ADDRESS=deployed_contract_address_here

blockchain/.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Node.js / Next.js
2+
node_modules/
3+
.next/
4+
npm-debug.log
5+
package-lock.json
6+
# Python
7+
__pycache__/
8+
*.pyc
9+
.venv/
10+
11+
12+
# Hardhat
13+
artifacts/
14+
cache/
15+
typechain/
16+
17+
# Docker
18+
*.env
19+
docker-compose.override.yml
20+
21+
# VS Code
22+
.vscode/
23+
24+
# OS files
25+
.DS_Store
26+
Thumbs.db
27+
28+
# Project-specific
29+
.env
30+
*.txt
31+
DevSecOps_Blockchain_App.code-workspace
32+
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.20;
3+
4+
contract ProductRegistry {
5+
struct Product {
6+
string name;
7+
string batch;
8+
string manufacturer;
9+
string status;
10+
uint256 timestamp;
11+
bool exists;
12+
}
13+
14+
struct TraceRecord {
15+
string stage;
16+
string company;
17+
string location;
18+
uint256 timestamp;
19+
bool exists;
20+
}
21+
22+
mapping(string => Product) public products;
23+
mapping(string => TraceRecord[]) public productTraces;
24+
mapping(string => uint256) public traceCount;
25+
26+
event ProductRegistered(string productId, string name, string manufacturer);
27+
event ProductStatusUpdated(string productId, string newStatus);
28+
event TraceRecordAdded(string productId, string stage, string company, string location);
29+
30+
modifier productExists(string memory productId) {
31+
require(products[productId].exists, "Product does not exist");
32+
_;
33+
}
34+
35+
function registerProduct(
36+
string memory productId,
37+
string memory name,
38+
string memory batch,
39+
string memory manufacturer
40+
) public {
41+
require(!products[productId].exists, "Product already exists");
42+
require(bytes(productId).length > 0, "Product ID cannot be empty");
43+
require(bytes(name).length > 0, "Product name cannot be empty");
44+
require(bytes(manufacturer).length > 0, "Manufacturer cannot be empty");
45+
46+
products[productId] = Product({
47+
name: name,
48+
batch: batch,
49+
manufacturer: manufacturer,
50+
status: "Created",
51+
timestamp: block.timestamp,
52+
exists: true
53+
});
54+
55+
emit ProductRegistered(productId, name, manufacturer);
56+
}
57+
58+
function updateProductStatus(string memory productId, string memory newStatus)
59+
public
60+
productExists(productId)
61+
{
62+
require(bytes(newStatus).length > 0, "Status cannot be empty");
63+
64+
products[productId].status = newStatus;
65+
emit ProductStatusUpdated(productId, newStatus);
66+
}
67+
68+
function addTraceRecord(
69+
string memory productId,
70+
string memory stage,
71+
string memory company,
72+
string memory location
73+
) public productExists(productId) {
74+
require(bytes(stage).length > 0, "Stage cannot be empty");
75+
require(bytes(company).length > 0, "Company cannot be empty");
76+
require(bytes(location).length > 0, "Location cannot be empty");
77+
78+
TraceRecord memory newTrace = TraceRecord({
79+
stage: stage,
80+
company: company,
81+
location: location,
82+
timestamp: block.timestamp,
83+
exists: true
84+
});
85+
86+
productTraces[productId].push(newTrace);
87+
traceCount[productId] = productTraces[productId].length;
88+
89+
emit TraceRecordAdded(productId, stage, company, location);
90+
}
91+
92+
function getProduct(string memory productId)
93+
public
94+
view
95+
returns (
96+
string memory,
97+
string memory,
98+
string memory,
99+
string memory,
100+
uint256
101+
)
102+
{
103+
require(products[productId].exists, "Product not found");
104+
Product memory p = products[productId];
105+
return (p.name, p.batch, p.manufacturer, p.status, p.timestamp);
106+
}
107+
108+
function getTraceRecord(string memory productId, uint256 index)
109+
public
110+
view
111+
returns (
112+
string memory,
113+
string memory,
114+
string memory,
115+
uint256
116+
)
117+
{
118+
require(products[productId].exists, "Product not found");
119+
require(index < productTraces[productId].length, "Trace record index out of bounds");
120+
121+
TraceRecord memory trace = productTraces[productId][index];
122+
return (trace.stage, trace.company, trace.location, trace.timestamp);
123+
}
124+
125+
function getTraceCount(string memory productId)
126+
public
127+
view
128+
returns (uint256)
129+
{
130+
require(products[productId].exists, "Product not found");
131+
return traceCount[productId];
132+
}
133+
134+
function getAllTraces(string memory productId)
135+
public
136+
view
137+
returns (
138+
string[] memory stages,
139+
string[] memory companies,
140+
string[] memory locations,
141+
uint256[] memory timestamps
142+
)
143+
{
144+
require(products[productId].exists, "Product not found");
145+
146+
uint256 count = productTraces[productId].length;
147+
stages = new string[](count);
148+
companies = new string[](count);
149+
locations = new string[](count);
150+
timestamps = new uint256[](count);
151+
152+
for (uint256 i = 0; i < count; i++) {
153+
TraceRecord memory trace = productTraces[productId][i];
154+
stages[i] = trace.stage;
155+
companies[i] = trace.company;
156+
locations[i] = trace.location;
157+
timestamps[i] = trace.timestamp;
158+
}
159+
160+
return (stages, companies, locations, timestamps);
161+
}
162+
163+
function productExistsCheck(string memory productId)
164+
public
165+
view
166+
returns (bool)
167+
{
168+
return products[productId].exists;
169+
}
170+
171+
// Emergency function to verify contract integrity
172+
function getContractInfo()
173+
public
174+
pure
175+
returns (string memory, string memory)
176+
{
177+
return ("ProductRegistry", "2.0.0");
178+
}
179+
}

blockchain/hardhat.config.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require("dotenv").config();
2+
console.log("PRIVATE_KEY:", process.env.PRIVATE_KEY);
3+
console.log("INFURA_API_KEY:", process.env.INFURA_API_KEY);
4+
console.log("CONTRACT_ADDRESS:", process.env.CONTRACT_ADDRESS);
5+
6+
require("@nomiclabs/hardhat-ethers");
7+
8+
module.exports = {
9+
solidity: "0.8.20",
10+
defaultNetwork: "sepolia",
11+
networks: {
12+
hardhat: {},
13+
sepolia: {
14+
url: `https://sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`,
15+
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY.trim()] : [],
16+
},
17+
},
18+
paths: {
19+
sources: "./contracts",
20+
tests: "./test",
21+
cache: "./cache",
22+
artifacts: "./artifacts",
23+
},
24+
};

blockchain/scripts/deploy.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const hre = require("hardhat");
2+
3+
async function main() {
4+
console.log("Deploying to Sepolia...");
5+
6+
const ProductRegistry = await hre.ethers.getContractFactory("ProductRegistry");
7+
const registry = await ProductRegistry.deploy();
8+
9+
await registry.deployed();
10+
console.log("✅ Contract deployed to:", registry.address);
11+
}
12+
13+
main().catch((error) => {
14+
console.error(error);
15+
process.exitCode = 1;
16+
});

terraform/common/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ provider "aws" {
1212
region = var.aws_region
1313
}
1414

15-
# Tạo VPC..
15+
# Tạo VPC...
1616
module "vpc" {
1717
source = "../modules/vpc"
1818

terraform/environments/dev/outputs.tf

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ output "dynamodb_table_name" {
55

66
output "lambda_functions" {
77
description = "ARNs of the Lambda functions"
8-
value = {
9-
product_service = module.product_service.function_arn
10-
trace_service = module.trace_service.function_arn
11-
user_service = module.user_service.function_arn
12-
}
8+
value = module.lambda_service.lambda_function_arn
139
}
1410

1511
output "api_gateway_endpoint" {

terraform/environments/dev/variables.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ variable "public_subnets" {
4949
variable "app_version" {
5050
description = "Version of the application"
5151
type = string
52-
default = "158b2cd63572d3115e89204ad3786762eac77996"
52+
default = "158b2cd63572d3115e89204ad3786762eac77996"
5353
}
5454

5555
variable "cognito_user_pool_id" {

terraform/environments/prod/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ terraform {
88
}
99
}
1010

11+
#run
12+
1113
provider "aws" {
1214
region = var.aws_region
1315
}

terraform/environments/prod/outputs.tf

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ output "dynamodb_table_name" {
55

66
output "lambda_functions" {
77
description = "ARNs of the Lambda functions"
8-
value = {
9-
product_service = module.product_service.function_arn
10-
trace_service = module.trace_service.function_arn
11-
user_service = module.user_service.function_arn
12-
}
8+
value = module.lambda_service.lambda_function_arn
139
}
1410

1511
output "api_gateway_endpoint" {

0 commit comments

Comments
 (0)