Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
84070a1
remove OS config concept
wanwiset25 Jan 29, 2025
cc8701d
remove docker-compose.env concept
wanwiset25 Feb 6, 2025
24caccd
fix single machine IP assignment
wanwiset25 Feb 10, 2025
6d83c5c
add subswap-frontend docker compose generation
wanwiset25 Feb 17, 2025
14f8ea0
update default values in common.env and contract_deploy.env
wanwiset25 Feb 18, 2025
f8fd4d2
new commands.txt and remove some defaults in generated .env
wanwiset25 Feb 19, 2025
69c9225
remove gen deployment (no need in new csc scheme)
wanwiset25 Feb 20, 2025
24f6b82
fix command
wanwiset25 Feb 20, 2025
115bfa8
container manager concept
wanwiset25 Feb 25, 2025
3c049bf
make docker-compose paths work with container-manager
wanwiset25 Feb 25, 2025
d2d6fed
reorg files and add stream events feature
wanwiset25 Feb 26, 2025
e4cc0d1
add check state for current block and peers
wanwiset25 Feb 27, 2025
a1492b3
format code
wanwiset25 Feb 27, 2025
98b614a
containerized and tested working
wanwiset25 Feb 27, 2025
0dab6f3
make execute stream work and reorganize code
wanwiset25 Mar 4, 2025
2042a26
add history and auto collapse old output
wanwiset25 Mar 4, 2025
ddf46a2
integrate gen config
wanwiset25 Mar 23, 2025
5c5c210
refactor code to generate subnet files
wanwiset25 Mar 24, 2025
1cb7450
integrate genesis and versioning
wanwiset25 Mar 24, 2025
7e31dcc
detect more state and add pre-configured options
wanwiset25 Apr 4, 2025
5d9f465
more dynamic ui according to the current state
wanwiset25 Apr 6, 2025
442c21e
contract state detection and display
wanwiset25 Apr 7, 2025
446d868
add stop button and more pre-configured options
wanwiset25 Apr 8, 2025
4a36ffc
add loading to prevent double command
wanwiset25 Apr 9, 2025
e3f0810
formatting
wanwiset25 Apr 9, 2025
23bc090
add more states
wanwiset25 Apr 14, 2025
227ed24
add check mining UI and aesthetic improvements
wanwiset25 Apr 16, 2025
092e76f
bump subnet version
wanwiset25 Apr 22, 2025
4ce8110
update cicd and start script
wanwiset25 Apr 22, 2025
9572f41
use HOSTPWD instead of PWD when running inside container
wanwiset25 Apr 22, 2025
6d510ee
update start script
wanwiset25 Apr 23, 2025
f27bec9
update logic for checking deploy state
wanwiset25 Apr 23, 2025
3ccb207
minor fix and use autoformatter
wanwiset25 Apr 23, 2025
61e6d6d
fix bug where config object is frozen too early
wanwiset25 Apr 24, 2025
3b93af3
update mainnet rpc url
wanwiset25 Apr 24, 2025
d7c561d
bump versions for release
wanwiset25 Apr 24, 2025
8aa550f
update contract deploy state check logic
wanwiset25 Apr 24, 2025
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
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: Build and update image
on:
push:
branches:
- main
- master
- generator*
paths:
- deployment-generator/**
- container-manager/**
tags:
- '*'
workflow_dispatch: #allow manual trigger to workflow
Expand All @@ -18,7 +18,7 @@ jobs:
environment: DockerHub
defaults:
run:
working-directory: subnet/deployment-generator
working-directory: container-manager/
steps:
- name: Check out code
uses: actions/checkout@v3
Expand All @@ -41,8 +41,8 @@ jobs:

- name: Build and push image
run: |
docker build . --file docker/Dockerfile \
--build-arg SUBNET_BRANCH=${{ steps.commit.outputs.commit}} \
docker build . --file Dockerfile \
--build-arg SUBNET_BRANCH=${{ steps.commit.outputs.commit}} \
--build-arg IMAGE_NAME=${{ steps.image.outputs.name }} \
--tag ${{ steps.image.outputs.name }}
docker push ${{ steps.image.outputs.name }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ keys.json
node_modules
package-lock.json
generated
mount
*.env*
**temp
*key*
Expand Down
1 change: 1 addition & 0 deletions container-manager/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
21 changes: 21 additions & 0 deletions container-manager/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Use the official Node.js 18.15 image as the base
FROM node:18.15

# Install Docker CLI (required to interact with the Docker API)
RUN apt-get update && apt-get install -y \
curl \
&& curl -fsSL https://get.docker.com | sh

# # Optionally, switch to a non-root user (for testing permissions)
# RUN useradd -m myuser
# USER myuser

COPY /src /app

# Set the working directory
WORKDIR /app

RUN npm install

# CMD ["sleep", "infinity"]
CMD ["npm", "run", "start"]
236 changes: 236 additions & 0 deletions container-manager/src/express.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
process.chdir(__dirname);
const fs = require("fs");
const state = require("./libs/state");
const exec = require("./libs/exec");
const path = require("path");
const ethers = require("ethers");
const consolidate = require("consolidate");
const express = require("express");
const app = express();
const PORT = 5210;
let lastCalled = Date.now();

app.engine("pug", consolidate.pug);
app.engine("html", consolidate.swig);
app.set("view engine", "html"); // Set default to HTML
app.set("json spaces", 2);
app.use(express.static(path.join(__dirname, "public")));
app.use(
express.urlencoded({
extended: true,
})
);
app.use(express.json());

app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "views", "index.html"));
});

app.get("/debug", (req, res) => {
res.sendFile(path.join(__dirname, "views", "debug.html"));
});

app.get("/state", async (req, res) => {
console.log("/state called");
const thisCall = Date.now();
console.log("time form last call: ", thisCall - lastCalled);
lastCalled = thisCall;
const response = await state.getState();
res.setHeader("Content-Type", "application/json");
res.send(JSON.stringify(response, null, 2));
});

app.get("/deploy_csc_lite", async (req, res) => {
console.log("/deploy_csc_lite called");
await exec.deployCSC("lite", setupRes(req, res));
});
app.get("/deploy_csc_full", async (req, res) => {
console.log("/deploy_csc_full called");
await exec.deployCSC("full", setupRes(req, res));
});
app.get("/deploy_csc_reversefull", async (req, res) => {
console.log("/deploy_csc_reversefull called");
await exec.deployCSC("reversefull", setupRes(req, res));
});

app.get("/deploy_zero", async (req, res) => {
console.log("/deploy_zero called");
await exec.deployZero(setupRes(req, res));
});

app.get("/deploy_subswap", async (req, res) => {
console.log("/deploy_subswap called");
await exec.deploySubswap(setupRes(req, res));
});

app.get("/start_subnet", async (req, res) => {
console.log("/start_subnet called");
await exec.startComposeProfile("machine1", setupRes(req, res));
});

app.get("/stop_subnet", async (req, res) => {
console.log("/stop_subnet called");
const callbacks = setupRes(req, res);
await exec.stopComposeProfile("machine1", callbacks);
});

app.get("/start_subnet_slow", async (req, res) => {
console.log("/start_subnet_slow called");
await exec.startSubnet("machine1", setupRes(req, res));
});

app.get("/start_services", async (req, res) => {
console.log("/start_services called");
await exec.startComposeProfile("services", setupRes(req, res));
});

app.get("/stop_services", async (req, res) => {
console.log("/stop_services called");
await exec.stopComposeProfile("services", setupRes(req, res));
});

app.get("/start_subswap_frontend", async (req, res) => {
console.log("/start_subswap_frontend called");
await exec.startComposeProfile("subswap", setupRes(req, res));
});

app.get("/stop_subswap_frontend", async (req, res) => {
console.log("/stop_subswap_frontend called");
await exec.stopComposeProfile("subswap", setupRes(req, res));
});

app.get("/start_explorer", async (req, res) => {
console.log("/start_explorer called");
await exec.startComposeProfile("explorer", setupRes(req, res));
});

app.get("/stop_explorer", async (req, res) => {
console.log("/stop_explorer called");
await exec.stopComposeProfile("explorer", setupRes(req, res));
});

app.get("/remove_subnet", async (req, res) => {
console.log("/remove_subnet called");
await exec.stopComposeProfile("machine1", setupRes(req, res));
});

// generator methods (also pug instead of html)
app.get("/gen", (req, res) => {
res.render("generator/index.pug", {});
});

app.post("/submit", (req, res) => {
console.log("/submit called");
const [valid, genOut] = exec.generate(req.body);

if (!valid) {
res.render("generator/submit.pug", {
message: "failed, please try again",
error: genOut,
});
} else {
res.render("generator/submit.pug", {
message:
"Config generation success, please continue in the Deployment Wizard tab",
});
}
});

app.post("/submit_preconfig", (req, res) => {
console.log("/submit called");
const [valid, genOut] = exec.generate(req.body);

if (!valid) {
res.send("failed to generate");
} else {
res.send("success");
}
});

app.get("/address", (req, res) => {
const randomWallet = ethers.Wallet.createRandom();
res.json({
publicKey: randomWallet.address,
privateKey: randomWallet.privateKey,
});
});

// add method to create env with pk, then faucet wallet will create from that file
app.get("/faucet", (req, res) => {
res.render("faucet/index.pug", {});
});

app.get("/faucet_subnet", async function (req, res) {
console.log("/faucet_subnet called");
console.log(req.query);
try {
const { subnetUrl, gmKey } = state.getFaucetParams();
const provider = new ethers.JsonRpcProvider(subnetUrl);
const fromWallet = new ethers.Wallet(gmKey, provider);
const fromPK = "123";
toAddress = req.query.dest;
amount = req.query.amount;
if (!ethers.isAddress(toAddress))
throw Error("Invalid destination address");
if (isNaN(Number(amount)) || parseFloat(amount) <= 0 || amount == "")
throw Error("Invalid Amount");
if (parseFloat(amount) > 1_000_000_000)
throw Error("Faucet request over 1,000,000,000 is not allowed");
let inputs = ["", "", fromPK, toAddress, amount];
const { fromBalance, toBalance, txHash } = await exec.processTransfer(
provider,
fromWallet,
toAddress,
amount
);
res.json({
success: true,
sourceAddress: fromWallet.address,
destAddress: toAddress,
sourceBalance: fromBalance,
destBalance: toBalance,
txHash: txHash,
});
} catch (error) {
console.log(error);
console.log(error.message);
res.json({
success: false,
message: error.message,
});
}
});

app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

function sleepSync(ms) {
const start = Date.now();
while (Date.now() - start < ms) {
// Busy-wait loop (blocks the event loop)
}
}

function setupRes(req, res) {
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
const dataCallback = (data) => {
lines = data.split("\n");
for (let l = 0; l < lines.length; l++) {
res.write(`data:${lines[l]}\n\n`);
}
};
const doneCallback = () => {
res.write("event: close\ndata: Done\n\n");
res.end();
};
req.on("close", () => {
res.end();
});
return {
dataCallback: dataCallback,
doneCallback: doneCallback,
};
}
Loading