Skip to content
Draft
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
16 changes: 16 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,25 @@ DEPLOYER_PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE

# RPC endpoint for the target network (Infura, Alchemy, etc.)
RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
# Optional per-network RPC overrides
MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID
POLYGON_RPC_URL=https://polygon-mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID

# Etherscan API key for contract verification
ETHERSCAN_API_KEY=YOUR_ETHERSCAN_API_KEY

# Set to "true" to enable gas reporting in tests
REPORT_GAS=false

# Cloudflare Worker secret for API authorization
API_SECRET=YOUR_WORKER_API_SECRET

# Optional Worker defaults
NETWORK=mainnet
TOKEN_CONTRACT_ADDRESS=0xYOUR_DEPLOYED_TOKEN_ADDRESS
TOKEN_BYTECODE=0xYOUR_COMPILED_CONTRACT_BYTECODE
DEPLOYER_ADDRESS=0xYOUR_DEPLOYER_ADDRESS
FINANCE_TICKER=SAMPLE1
JOB_SKILLS=solidity,cloudflare,workers
JOB_LOCATION=remote
47 changes: 47 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Deploy Cloudflare Worker

on:
push:
branches:
- main

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint

deploy-worker:
runs-on: ubuntu-latest
needs: [test, lint]
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx wrangler deploy
123 changes: 121 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,121 @@
# Cf-
Confirm configuration
# CreatingFire Ecosystem

CreatingFire Ecosystem unifies the `Cf-` ERC20 token contract and Theodore's multi-agent automation system behind a Cloudflare Worker orchestration layer.

## System Overview

- **Smart contract layer**: ERC20 token (`contracts/ERC20_Token_Sample.sol`) with burn features.
- **Orchestration layer**: Cloudflare Worker (`src/worker.js`) for token operations + multi-agent routes.
- **Agent layer**:
- `src/agents/finance.js`
- `src/agents/jobs.js`
- `src/agents/toolchain.js`
- **Data layer**:
- KV: `AGENT_STATE`, `TOKEN_CACHE`
- D1: `THEODORE_DB` with schema at `src/db/schema.sql`

## Architecture Diagram (ASCII)

```text
┌──────────────────────────────┐
│ Cloudflare Worker API │
│ src/worker.js │
└───────┬────────────┬─────────┘
│ │
┌──────────▼───────┐ ┌──▼────────────────┐
│ ERC20 on-chain │ │ Multi-Agent Layer │
│ deploy/status/burn│ │ finance/jobs/tools│
└──────────┬───────┘ └──┬────────────────┘
│ │
┌──────▼──────┐ ┌────▼──────────────┐
│ JSON-RPC │ │ KV + D1 Storage │
│ (RPC_URL) │ │ state/events/runs │
└─────────────┘ └───────────────────┘
```

## Setup

1. Clone and install dependencies:
```bash
git clone https://github.com/creatingfire2026/Cf-.git
cd Cf-
npm install
```
2. Configure environment values:
```bash
cp .env.example .env
```
3. Configure Cloudflare secrets/vars:
- `wrangler.toml`
- `wrangler secret put API_SECRET`
- `wrangler secret put RPC_URL`
4. Apply D1 schema:
```bash
npx wrangler d1 execute THEODORE_DB --file=src/db/schema.sql
```
5. Deploy Worker:
```bash
npm run worker:deploy
```

## API Endpoints

All endpoints require:

- Header: `Authorization` must include the API secret token
- JSON response envelope: `{ success, data, timestamp }`

### Health
- `GET /` — system health and binding status

### Token
- `POST /token/deploy` — deploy via JSON-RPC (`eth_sendRawTransaction` or `eth_sendTransaction`)
- `GET /token/status?contractAddress=0x...` — token name/symbol/supply
- `POST /token/burn` — call `burnTokens(amount)`

### Agents
- `POST /agent/finance` — ticker/query analysis (mock structure)
- `POST /agent/jobs` — skill/location job search (mock structure)
- `POST /agent/toolchain` — toolchain optimization suggestions
- `GET /agent/status` — aggregate status from KV

### Scheduling
- `POST /cron` — manual trigger for scheduled orchestration tasks
- Scheduled cron (`0 * * * *`) runs the same orchestration logic automatically

## Environment Variables

| Variable | Used by | Purpose |
|---|---|---|
| `DEPLOYER_PRIVATE_KEY` | Hardhat | Deployment signer key |
| `RPC_URL` | Hardhat + Worker | Chain RPC endpoint |
| `MAINNET_RPC_URL` | Hardhat | Optional mainnet-specific RPC override |
| `SEPOLIA_RPC_URL` | Hardhat | Optional sepolia-specific RPC override |
| `POLYGON_RPC_URL` | Hardhat | Optional polygon-specific RPC override |
| `ETHERSCAN_API_KEY` | Hardhat | Verification API key |
| `REPORT_GAS` | Hardhat | Enable gas reporting (`true`/`false`) |
| `API_SECRET` | Worker | API endpoint authorization token |
| `NETWORK` | Worker vars | Target network label (`mainnet`) |
| `TOKEN_CONTRACT_ADDRESS` | Worker | Default token address for status/burn |
| `TOKEN_BYTECODE` | Worker | Optional default deployment bytecode |
| `DEPLOYER_ADDRESS` | Worker | Optional unlocked RPC deploy/burn sender |
| `FINANCE_TICKER` | Worker | Scheduled finance ticker (default `SAMPLE1`) |
| `JOB_SKILLS` | Worker | Comma-separated scheduled job skills |
| `JOB_LOCATION` | Worker | Scheduled job location (default `remote`) |

## GitHub Actions CI/CD

- `test.yml`: compiles and tests Hardhat project.
- `deploy.yml`:
- Runs `npm test`
- Runs `npm run lint`
- Deploys Worker with `wrangler deploy` after successful checks

Required GitHub secrets for deployment:
- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`

## Repository Links

- ERC20 + orchestration repo: https://github.com/creatingfire2026/Cf-
- Theodore's Multi-Agent System repo: https://github.com/creatingfire2026/Theodore-s-Automated-copilot-Multi-Agent-System
65 changes: 65 additions & 0 deletions hardhat.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,71 @@
require("dotenv").config();
require("@nomicfoundation/hardhat-ethers");
require("@nomicfoundation/hardhat-chai-matchers");

const {
TASK_COMPILE_SOLIDITY_GET_SOLC_BUILD,
} = require("hardhat/builtin-tasks/task-names");

/**
* Overrides the default Solidity compiler build resolution to fall back to the
* locally installed `solc` npm package when the compiler binary cannot be
* downloaded from the internet (e.g. in CI or restricted network environments).
*
* @param {object} args - Subtask arguments (solcVersion, quiet).
* @param {object} _hre - Hardhat Runtime Environment (unused).
* @param {Function} runSuper - The default subtask implementation.
* @returns {{ compilerPath: string, isSolcJs: boolean, version: string, longVersion: string }}
*/
subtask(TASK_COMPILE_SOLIDITY_GET_SOLC_BUILD, async (args, _hre, runSuper) => {
try {
return await runSuper(args);
} catch (_err) {
const { version } = require("solc/package.json");
return {
compilerPath: require.resolve("solc/soljson.js"),
isSolcJs: true,
version,
longVersion: version,
};
}
});

const {
DEPLOYER_PRIVATE_KEY,
RPC_URL,
MAINNET_RPC_URL,
SEPOLIA_RPC_URL,
POLYGON_RPC_URL,
ETHERSCAN_API_KEY,
REPORT_GAS,
} = process.env;

const accounts = DEPLOYER_PRIVATE_KEY ? [DEPLOYER_PRIVATE_KEY] : [];

module.exports = {
solidity: "0.8.26",
networks: {
mainnet: {
url: MAINNET_RPC_URL || RPC_URL || "http://127.0.0.1:8545",
accounts,
},
sepolia: {
url: SEPOLIA_RPC_URL || RPC_URL || "http://127.0.0.1:8545",
accounts,
},
polygon: {
url: POLYGON_RPC_URL || RPC_URL || "http://127.0.0.1:8545",
accounts,
},
localhost: {
url: "http://127.0.0.1:8545",
accounts,
},
},
gasReporter: {
enabled: REPORT_GAS === "true",
},
etherscan: {
apiKey: ETHERSCAN_API_KEY || "",
},
};
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"test": "hardhat test",
"coverage": "hardhat coverage",
"lint": "solhint 'contracts/**/*.sol'",
"clean": "hardhat clean"
"clean": "hardhat clean",
"worker:dev": "wrangler dev",
"worker:deploy": "wrangler deploy"
},
"devDependencies": {
"@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
Expand Down
60 changes: 60 additions & 0 deletions src/agents/finance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { formatUnits } from "ethers";
import { callTokenMethod, rpcRequest } from "./tokenRpc.js";

export async function analyzeToken(contractAddress, env) {
if (!contractAddress) {
throw new Error("contractAddress is required");
}

const name = await callTokenMethod(contractAddress, "name", env);
const symbol = await callTokenMethod(contractAddress, "symbol", env);
const totalSupply = await callTokenMethod(contractAddress, "totalSupply", env);
const blockNumberHex = await rpcRequest(env, "eth_blockNumber", []);

return {
contractAddress,
name,
symbol,
totalSupply: totalSupply.toString(),
totalSupplyFormatted: formatUnits(totalSupply, 18),
blockNumber: Number.parseInt(blockNumberHex, 16),
};
}

export async function getMarketSnapshot(ticker = "SAMPLE1", env) {
return {
ticker,
source: "placeholder",
sentiment: "neutral",
confidence: 0,
metrics: {
priceUsd: null,
volume24h: null,
marketCap: null,
change24hPercent: null,
},
note: "Replace with real market data provider integration",
generatedAt: new Date().toISOString(),
};
}

export async function storeSnapshot(data, env) {
if (!env.TOKEN_CACHE) {
throw new Error("Missing required binding: TOKEN_CACHE");
}

await env.TOKEN_CACHE.put("finance:latest", JSON.stringify(data), {
expirationTtl: 3600,
});

return { stored: true, key: "finance:latest", ttlSeconds: 3600 };
}

export async function getLatestSnapshot(env) {
if (!env.TOKEN_CACHE) {
throw new Error("Missing required binding: TOKEN_CACHE");
}

const raw = await env.TOKEN_CACHE.get("finance:latest");
return raw ? JSON.parse(raw) : null;
}
Loading