Skip to content

Commit 846ee4a

Browse files
committed
init repo structure, basic smart contract implementation
0 parents  commit 846ee4a

19 files changed

Lines changed: 6514 additions & 0 deletions

.github/copilot-instructions.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SmartClaws
2+
3+
IoT data platform on SKALE blockchain. On-chain message channels for device-to-agent communication, Python SDK for hardware integration.
4+
5+
## Smart Contracts (`smart-contracts/`)
6+
7+
Hardhat 3, ESM, Solidity 0.8.28, OpenZeppelin 5.x.
8+
9+
**Contracts:** `SmartClaws` (registry) → creates `SmartClawsChannel` (append-only message log), `SmartClawsDeviceGroup` (manages devices), `SmartClawsAgent` (AI agent with channels), `SmartClawsDevice` (device record).
10+
11+
**Key patterns:** custom errors (not require strings), `Ownable2Step`, `EnumerableSet`, `unchecked` increments. HH3 uses `defineConfig` + `plugins` array, ethers via `await hre.network.connect()`.
12+
13+
**Commands:** `npm test`, `npm run compile`, `npm run lint`.
14+
15+
## Python
16+
17+
Python 3.10+, managed with `uv`. BLE utilities for sensor communication.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Smart Contracts
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "smart-contracts/**"
8+
pull_request:
9+
branches: [main]
10+
paths:
11+
- "smart-contracts/**"
12+
13+
jobs:
14+
test:
15+
name: Compile, Lint & Test
16+
runs-on: ubuntu-latest
17+
defaults:
18+
run:
19+
working-directory: smart-contracts
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- uses: actions/setup-node@v4
25+
with:
26+
node-version: 22
27+
28+
- run: npm ci
29+
30+
- name: Compile contracts
31+
run: npx hardhat compile
32+
33+
- name: Lint Solidity
34+
run: npx solhint 'contracts/**/*.sol'
35+
36+
- name: Run tests
37+
run: npx hardhat test

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.egg-info/
5+
dist/
6+
build/
7+
.venv/
8+
*.so
9+
10+
# Node.js
11+
node_modules/
12+
13+
# Hardhat / Solidity
14+
artifacts/
15+
cache/
16+
typechain-types/
17+
types/
18+
*.dbg.json
19+
coverage/
20+
coverage.json
21+
22+
# Environment & secrets
23+
.env
24+
.env.*
25+
26+
# OS
27+
.DS_Store
28+
Thumbs.db
29+
30+
# IDE
31+
.idea/
32+
.vscode/
33+
*.swp
34+
*.swo
35+
36+
# Project-specific
37+
context/
38+
.claude/
39+
uv.lock
40+
*.log

python/pyproject.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[project]
2+
name = "smartclaws"
3+
version = "0.1.0"
4+
requires-python = ">=3.10"
5+
dependencies = ["bleak"]
6+
7+
[dependency-groups]
8+
dev = ["ruff"]
9+
10+
[tool.ruff]
11+
line-length = 120
12+
target-version = "py310"
13+
14+
[tool.ruff.lint]
15+
select = ["E", "F", "I"]

python/read.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import asyncio
2+
from bleak import BleakClient, BleakScanner
3+
from datetime import datetime
4+
5+
# The GATT characteristic that sends temp/humidity notifications
6+
DATA_CHAR = "ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6"
7+
8+
9+
async def scan():
10+
devices = await BleakScanner.discover(timeout=10)
11+
for d in devices:
12+
if d.name and "LYWSD03" in d.name:
13+
print(f"{d.name} -> {d.address}")
14+
15+
16+
async def read(address: str):
17+
async with BleakClient(address) as client:
18+
data = await client.read_gatt_char(DATA_CHAR)
19+
temp = int.from_bytes(data[0:2], "little", signed=True) / 100
20+
humi = data[2]
21+
voltage = int.from_bytes(data[3:5], "little") / 1000
22+
print(f"Temperature: {temp}°C")
23+
print(f"Humidity: {humi}%")
24+
print(f"Voltage: {voltage}V")
25+
26+
27+
async def read_loop(address: str, interval: float = 2.0):
28+
async with BleakClient(address) as client: # connect once
29+
while True:
30+
data = await client.read_gatt_char(DATA_CHAR)
31+
temp = int.from_bytes(data[0:2], "little", signed=True) / 100
32+
humi = data[2]
33+
print(f"{temp}°C / {humi}%")
34+
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
35+
await asyncio.sleep(interval)
36+
37+
38+
# Scan to find MACs (only needed once):
39+
# asyncio.run(scan())
40+
41+
# Read with your known MAC:
42+
# asyncio.run(read("229C6152-3E39-45DB-3A8B-D48CB72D171F"))
43+
# asyncio.run(read("99C9B552-C48E-0764-B56E-916ADDD6A0EA"))
44+
asyncio.run(read_loop("99C9B552-C48E-0764-B56E-916ADDD6A0EA", interval=0))

python/scan.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import asyncio
2+
from bleak import BleakScanner
3+
4+
async def scan():
5+
devices = await BleakScanner.discover(timeout=10)
6+
for d in devices:
7+
if d.name and "LYWSD03" in d.name:
8+
print(f"{d.name} -> {d.address}")
9+
10+
asyncio.run(scan())

smart-contracts/.solhint.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "solhint:recommended",
3+
"rules": {
4+
"func-visibility": ["warn", { "ignoreConstructors": true }],
5+
"no-empty-blocks": "off",
6+
"compiler-version": ["error", "^0.8.28"],
7+
"max-line-length": ["warn", 120],
8+
"use-natspec": "off",
9+
"immutable-vars-naming": "off",
10+
"gas-strict-inequalities": "off"
11+
}
12+
}

smart-contracts/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# SmartClaws Smart Contracts
2+
3+
On-chain message channels and device registry for the SmartClaws IoT platform, built on SKALE.
4+
5+
## Contracts
6+
7+
| Contract | Description |
8+
|---|---|
9+
| `SmartClaws` | Global registry — creates and tracks channels, device groups, and agents |
10+
| `SmartClawsChannel` | Append-only message log with circular buffer pruning by byte capacity |
11+
| `SmartClawsDeviceGroup` | Groups devices, handles registration and lifecycle |
12+
| `SmartClawsAgent` | AI agent with dedicated incoming and outgoing channels |
13+
| `SmartClawsDevice` | Immutable device record linking incoming/outgoing channels |
14+
15+
## Structure
16+
17+
```
18+
smart-contracts/
19+
├── contracts/ # Solidity source files
20+
├── test/ # Mocha + Ethers tests
21+
├── scripts/ # Deployment scripts
22+
├── hardhat.config.ts # Hardhat 3 config (ESM)
23+
└── .solhint.json # Solidity linter config
24+
```
25+
26+
## Commands
27+
28+
```bash
29+
npm install # Install dependencies
30+
npm run compile # Compile contracts
31+
npm test # Run tests
32+
npm run lint # Lint Solidity
33+
```
34+
35+
## Deploy
36+
37+
Set `SKALE_RPC_URL` and `DEPLOYER_PRIVATE_KEY` in `.env`, then:
38+
39+
```bash
40+
npx hardhat run scripts/deploy.ts --network skaleTestnet
41+
```
42+
43+
## Stack
44+
45+
- Hardhat 3 (ESM, TypeScript)
46+
- Solidity 0.8.28, optimizer enabled, cancun EVM
47+
- OpenZeppelin Contracts 5.x
48+
- Mocha + Chai + Ethers.js

0 commit comments

Comments
 (0)